java - programacion - ¿Cómo forzar a una clase a ser inicializada?
manual de programacion android pdf (6)
Cargando! = Inicialización.
Desea que su clase se inicialice (esto es cuando se ejecutan bloques estáticos, entre otras cosas).
Un extracto de la Especificación del lenguaje Java dice:
Una clase o interfaz de tipo T se inicializará inmediatamente antes de la primera aparición de> cualquiera de los siguientes:
- T es una clase y se crea una instancia de T.
- T es una clase y se invoca un método estático declarado por T.
- Se asigna un campo estático declarado por T.
- Se utiliza un campo estático declarado por T y el campo no es una variable constante (§4.12.4).
- T es una clase de nivel superior, y se ejecuta una declaración de afirmación (§14.10) léxicamente anidada dentro de T.
La invocación de ciertos métodos reflectantes en la clase Class y en el paquete java.lang.reflect también provoca la inicialización de la clase o la interfaz. Una clase o interfaz no se inicializará bajo ninguna otra circunstancia.
Doh, anovstrup, ya lo dijo: simplemente crea una función estática vacía llamada init
. Asegúrate de documentarlo bien ... Personalmente, no puedo ver ningún caso de uso para esto en el contexto de un código bien formado.
¿Cuál es la mejor y más limpia forma de hacer esto? Específicamente, necesito un código en un bloque de inicializador estático para ejecutar en esa clase, pero me gustaría que sea lo más limpio posible.
Las dependencias invisibles entre clases no son una buena idea. Sugiero mover el código en bloque de inicializador estático a un método estático y llamarlo directamente en la clase dependiente. El bloque de inicializador estático se puede volver a escribir para llamar al método estático recién creado.
Puede usar el siguiente código para forzar la inicialización de una clase:
//... Foo.class ... //OLD CODE
... forceInit(Foo.class) ... //NEW CODE
/**
* Forces the initialization of the class pertaining to
* the specified <tt>Class</tt> object.
* This method does nothing if the class is already
* initialized prior to invocation.
*
* @param klass the class for which to force initialization
* @return <tt>klass</tt>
*/
public static <T> Class<T> forceInit(Class<T> klass) {
try {
Class.forName(klass.getName(), true, klass.getClassLoader());
} catch (ClassNotFoundException e) {
throw new AssertionError(e); // Can''t happen
}
return klass;
}
Si necesita iniciar de forma estática algo en una clase, significa que debe haber clases de clientes que dependen de eso.
Si hay un cliente, o vamos a llamarlo un hogar natural para el bloque de inicialización, creo que sería más limpio inicializarlo allí.
Para el caso de muchos clientes iguales, puede ser una buena idea verificar a partir de estas clases que la iniciación estática en la otra clase fue exitosa. Entonces, el acoplamiento está documentado y está seguro de que la clase siempre se inicializa antes de que el primer cliente lo necesite.
Una solución sería llamar a un método estático:
public class A {
static { DebugUtils.FLAG_TEST_USER = true; }
static void init() {}
}
Luego invoque A.init()
para forzar la inicialización.
Sin embargo, hacer esto es un olor a código. Considere reemplazar su código estático con un constructor estándar en un objeto singleton.
try
{
Class.forName(class name as string)
}
catch(ClassNotFoundException e)
{
whatever
}
Deberias hacer eso.
@Longpoke
Tal vez estoy malinterpretando algo entonces. ¿Puedes crear un ejemplo donde se cargue una clase pero no se ejecute el inicializador estático? Aquí hay un ejemplo que no hace más que imprimir que se ha cargado:
package test;
public class TestStatic
{
public static void main(String[] args)
{
try
{
Class.forName("test.Static");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}
Con la siguiente clase estática que se está cargando:
package test;
public class Static
{
static
{
System.out.println("Static Initializer ran...");
}
}
Si los inicializadores estáticos no se ejecutan hasta que se cumplen las condiciones que enumeró, ¿por qué se ejecuta esta impresión cuando ejecuto mi prueba? ¿Cuál de las condiciones mencionadas estoy reuniendo?