studio programacion móviles gui desarrollo definicion curso aplicaciones java interface static-initialization

java - programacion - inicialización estática en la interfaz



programacion android pdf 2018 (5)

Intefaces no tiene ningún bloque 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; } }

Cuando traté de 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?


Las interfaces no deben tener efectos secundarios y eso incluso se aplica a 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á la interface Foo initialized ? Intenta adivinar y ejecutar código luego. La respuesta puede sorprenderte.


Nunca hay un punto para declarar un método estático en una interfaz. No pueden ser ejecutados por la llamada normal MyInterface.staticMethod (). (EDITAR: Dado que la última frase confundió a algunas personas, llamar a MyClass.staticMethod () ejecuta precisamente la implementación de staticMethod en MyClass, que si MyClass es una interfaz no puede existir!) Si las llamas especificando la clase de implementación MyImplementor.staticMethod () entonces debe conocer la clase real, por lo que es irrelevante si la interfaz la 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 de var declarado debe ser ejecutado. Como esta es una interfaz, esto es imposible.

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

Para responder algunos de los comentarios a continuación, la razón por la que no puede ejecutar "result = MyInterface.staticMethod ()" es que debería 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.


Puede solucionar el problema, si lo ve como un problema, al colocar 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); } } }

huellas dactilares:

Test Hello Static Hello Hello again Hello

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


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 implementar cambia la sintaxis de Java.

El punto es que no debe tener código en una interfaz (antes de Java 8) pero puede inicializar campos.

Por cierto, puede tener una clase o enumeración anidada que tenga tanto código como desee y puede invocar esto al inicializar un campo. ;)