inicialización estática en la interfaz


Cuando intenté escribir algo como esto:

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

El compilador no pudo compilarlo.

Pero cuando escribí algo como esto:

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

Y lo descompilé, vi la inicialización estática:

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
}

¿Podría explicarme este comportamiento?

Author: Sergey Morozov, 2013-11-01

5 answers

Puede tener inicialización estática, pero no puede tener un bloque estático. El hecho de que la inicialización estática necesite un bloque de código estático para implementarlo cambia la sintaxis de Java.

El punto es que no está destinado a tener código en una interfaz (antes de Java 8), pero se le permite inicializar campos.

Por cierto, puede tener una clase anidada o enumeración que tenga tanto código como desee y puede llamar a esto mientras inicializa un campo. ;)

 13
Author: Peter Lawrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-01 08:07:24

Las interfaces no deben tener efectos secundarios y eso incluso se aplica a los inicializadores estáticos. Tendrían un comportamiento altamente dependiente de la implementación de JVM. Mira el siguiente código

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() {
  }
}

¿Qué piensas, cuándo se imprimirá interface Foo initialized? Trate de adivinar y ejecutar el código después. La respuesta podría sorprenderte.

 19
Author: Holger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-01 08:54:09

Puede sortear el problema - si lo ve como un problema - poniendo una segunda clase no pública en el mismo archivo.

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";
  }
}

Probando esto con:

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);
    }
  }

}

Impresiones:

Test Hello
Static Hello
Hello again
Hello

Java es un lenguaje tan inteligente - hace que sea difícil hacer cosas estúpidas, pero no imposible. :)

 6
Author: OldCurmudgeon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-01 09:38:30

Intefaces no tiene bloques de inicialización. El siguiente fragmento de código puede ser útil..

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
Author: Siddappa Walake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-17 17:45:41

Nunca tiene sentido declarar un método estático en una interfaz. No pueden ser ejecutados por la llamada normal MyInterface.staticMethod (). (EDIT: Desde que la última frase confundió a algunas personas, llamando MyClass.staticMethod () ejecuta precisamente la implementación de staticMethod en MyClass, que si MyClass es una interfaz no puede existir!) Si los llama especificando la clase de implementación MyImplementor.staticMethod () entonces debe conocer la clase real, por lo que es irrelevante si la la interfaz lo contiene o no.

Más importante aún, los métodos estáticos nunca se anulan, y si intenta hacer:

MyInterface var = new MyImplementingClass();
var.staticMethod();

Las reglas para static dicen que el método definido en el tipo declarado de var debe ser ejecutado. Dado que esta es una interfaz, esto es imposible.

Por supuesto, siempre puede eliminar la palabra clave estática del método. Todo va a funcionar bien. Es posible que tenga que suprimir algunas advertencias si se llama desde un método de instancia.

Para responder a algunos de los comentarios a continuación, la razón por la que no puede ejecutar "result=MyInterface.staticMethod () " es que tendría que ejecutar la versión del método definido en MyInterface. Pero no puede haber una versión definida en MyInterface, porque es una interfaz. No tiene código, por definición.

 -1
Author: Manish Doshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-01 08:39:01