web-dev-qa-db-fra.com

initialisation statique dans l'interface

Quand j'ai essayé d'écrire quelque chose comme ça:

public interface MyInterface {
    static {
        System.out.println("Hello!");
    }
}

le compilateur n'a pas pu le compiler.

Mais quand j'ai écrit quelque chose comme ça:

interface MyInterface {
    Integer iconst = Integer.valueOf(1);
}

et décompilé, j'ai vu l'initialisation statique:

public interface MyInterface{
    public static final Java.lang.Integer i;

    static {};
      Code:
      0:   iconst_1
      1:   invokestatic    #1; //Method Java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      4:   putstatic       #2; //Field i:Ljava/lang/Integer;
      7:   return
}

Pourriez-vous s'il vous plaît expliquer ce comportement à moi?

40
Sergey Morozov

Vous pouvez avoir une initialisation statique, mais vous ne pouvez pas avoir un bloc statique. Le fait que l'initialisation statique nécessite un bloc de code statique à implémenter change la syntaxe Java. 

Le fait est que vous n'êtes pas censé avoir du code dans une interface (avant Java 8), mais que vous êtes autorisé à initialiser des champs. 

En passant, vous pouvez avoir une classe ou une énumération imbriquée qui contient autant de code que vous le souhaitez et que vous pouvez appeler lors de l’initialisation d’un champ. ;)

13
Peter Lawrey

Les interfaces ne doivent pas avoir d'effets secondaires et cela s'applique même aux initiateurs statiques Ils auraient un comportement fortement dépendant de la mise en œuvre de la machine virtuelle Java. Regardez le code suivant

public class InterfaceSideEffects {
  public static void main(String[] args) {
    System.out.println("InterfaceSideEffects.main()");
    Impl i=new Impl();
    System.out.println("Impl initialized");
    i.bla();
    System.out.println("Impl instance method invoked");
    Foo f=new Impl();
    System.out.println("Impl initialized and assigned to Foo");
    f.bla();
    System.out.println("Foo interface method invoked");
  }
}
interface Foo {
  int dummy=Bar.haveSideEffect();
  void bla();
}
class Bar {
  static int haveSideEffect() {
    System.out.println("interface Foo initialized");
    return 0;
  }
}
class Impl implements Foo {
  public void bla() {
  }
}

Que pensez-vous, quand interface Foo initialized sera-t-il imprimé? Essayez de deviner et d'exécuter du code après. La réponse pourrait vous surprendre.

20
Holger

Vous pouvez contourner le problème - si vous le voyez comme un problème - en plaçant une deuxième classe non publique dans le même fichier.

public interface ITest {
  public static final String hello = Hello.hello();
}

// You can have non-public classes in the same file.
class Hello {
  static {
    System.out.println("Static Hello");
  }
  public static String hello() {
    System.out.println("Hello again");
    return "Hello";
  }
}

Tester ceci avec:

public class Test {
  public void test() {
    System.out.println("Test Hello");
    System.out.println(ITest.hello);
  }

  public static void main(String args[]) {
    try {
      new Test().test();
    } catch (Throwable t) {
      t.printStackTrace(System.err);
    }
  }

}

impressions:

Test Hello
Static Hello
Hello again
Hello

Java est un langage si astucieux qu'il est difficile de faire des choses stupides, mais pas impossible. :)

6
OldCurmudgeon

Les interfaces n'ont pas de bloc d'initialisation. L'extrait de code suivant peut être utile.

public interface MyInterface {
public static final int a;// Compilation error as there is no way for 
                          // explicit initialization

}

public class MyClass {
public static final int a;// Still no error as there is another way to 
                          //initialize variable even though they are final.
 static{
    a=10;
   }

}
0
Siddappa Walake