¿Cómo forzar la inicialización de una clase? [cerrado]


¿Cuál es la mejor y más limpia manera de hacer esto? Específicamente, necesito algo de código en un bloque inicializador estático para ejecutarse en esa clase, pero me gustaría hacer que esto sea lo más limpio posible.

Author: OrangeDog, 2010-08-24

6 answers

Carga != 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 tipo de interfaz T se inicializará inmediatamente antes de la primera aparición de >cualquiera de las siguientes:

  • T es una clase y se crea una instancia de T.
  • T es una clase y un método estático declarado por T es invocar.
  • 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 instrucción assert (§14.10) anidada léxicamente dentro de T.

Invocación de ciertos métodos reflexivos en class Class y en package java.lang.reflect también causa inicialización de clase o interfaz. Una clase o interfaz no se inicializará bajo ninguna otra circunstancia.

Doh, anovstrup, ya lo dijo: Simplemente haga una función estática vacía llamada init. Asegúrese de documentar eso bien... Personalmente no puedo ver ningún caso de uso para esto en el contexto de código bien formado sin embargo.

 43
Author: L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳,
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
2010-08-24 19:27:05

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;
} 
 11
Author: Iulian,
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
2012-02-22 08:39:54
try
{
  Class.forName(class name as string)
}
catch(ClassNotFoundException e)
{
  whatever
}

Eso debería bastar.

@Longpoke

Tal vez estoy malinterpretando algo entonces. ¿Puede crear un ejemplo donde se carga una clase pero el inicializador estático se ejecuta no? Aquí hay un ejemplo que no hace más que imprimir lo que 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 cargada:

package test;

public class Static 
{
    static
    {
        System.out.println("Static Initializer ran...");
    }
}

Si los inicializadores estáticos no se ejecutan hasta que se cumplan las condiciones enumeradas, entonces por qué se ejecuta esta impresora cuando corro mi prueba? ¿Esa es cuál de sus condiciones enumeradas estoy cumpliendo?

 7
Author: BigMac66,
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
2010-08-24 20:32:28

Las dependencias invisibles entre clases no es una buena idea. Sugiero mover el código en static initializer block a un método estático y llamarlo directamente en la clase dependiente. El bloque del inicializador estático se puede reescribir para llamar al método estático recién creado.

 4
Author: Abhinav Sarkar,
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
2010-08-24 19:14:06

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 invoca A.init() para forzar la inicialización.

Sin embargo, hacer esto en absoluto es un olor a código. Considere reemplazar su código estático con un constructor estándar en un objeto singleton.

 1
Author: Aaron Novstrup,
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
2010-08-24 19:44:28

Si necesita inicializar estáticamente algo en una Clase, eso significa que debe haber clases cliente dependientes 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 inicialización estática en la otra clase fue exitosa. Entonces el acoplamiento está documentado y usted está seguro de que la clase es siempre inicializado antes de que el primer cliente lo necesite.

 0
Author: Peter Tillemans,
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
2010-08-24 19:20:55