6

tengo una clase que sostiene una montura grande de constantes generados como tal:Cómo eludir el límite de tamaño de un inicializador estático en Java para inicializar grandes cantidades de constantes

public class Constants extends SomeBaseClass { 

    // init() is defined in some base class... 
    public static final XXX KEY1 = init(...); 
    public static final XXX KEY2 = init(...); 
    public static final XXX KEY3 = init(...); 

    // ... 
    public static final XXX KEY2000 = init(...); 
} 

Cuando el número de constantes generados es muy alto, esto da como resultado un inicializador estático que es mayor que el límite superior para los tamaños de método de Java (es decir,> 64 kb), lo que da como resultado un error de compilación. Una solución es crear varios "métodos de inicialización de bloque" para bloques que pueden ser garantizados para producir menos de 64kb de código de bytes, de tal forma que encajan en un método:

public class Constants extends SomeBaseClass { 

    public static XXX KEY1; 
    public static XXX KEY2; 
    public static XXX KEY3; 

    // ... 
    public static XXX KEY2000; 

    static { 
    initialise0001To1000(); 
    initialise1001To2000(); 
    } 

    private static void initialise0001To1000() { 
    KEY1 = init(...); 
    KEY2 = init(...); 
    KEY3 = init(...); 
    // ... 
    } 

    private static void initialise1001To2000() { 
    // ... 
    KEY2000 = init(...); 
    } 
} 

El inconveniente de esto es que lo que pueda ya no declara las constantes como final, porque ya no se inicializan directamente en el inicializador estático.

Mi pregunta es, ¿cómo puedo eludir esa limitación de compilador/JVM de manera que todavía puedo generar constantes static final?

+0

¿Cómo terminó corriendo en este problema? ¿Es este código autogenerado desde otro archivo? – templatetypedef

+0

@templatetypedef: Este es un error real en el generador de código fuente de [jOOQ] (http://www.jooq.org). Genera claves primarias, claves únicas y claves foráneas como objetos constantes de una base de datos. Parece que 2000 claves son demasiado para que lo maneje jOOQ: https://groups.google.com/d/topic/jooq-user/2g96fI1Yrj8/discussion –

+0

¿Podría usar capas de herencia "ficticias" para esto? Tener una clase base con algún nombre que no sea de uso público que contenga 1000 constantes y tenga un inicializador estático configurado. ¿Entonces una clase derivada que agrega 1,000 más, una clase subderivada que agrega otros 1,000, etc.? Solo la clase más derivada se usará para cualquier propósito, excepto para la derivación de las otras clases en el ensamblado. – supercat

Respuesta

1

Finalmente fui por una solución que involucraba clases anidadas. Esto fue sugerido en un comentario al this answer here por el usuario Loadmaster.clases anidadas tienen dos ventajas:

  • Permiten para ocultar estos detalles de implementación solución desde el mundo exterior por ser private clases anidadas
  • Permiten mantener constantes final

pero también tienen una desventaja en comparación con la solución templatetypedef's:

  • Me encontraré con el mismo problema de nuevo con mucho lar ger los números de las constantes

En este momento, sin embargo, esto parece ser la solución más adecuada:

public class Constants { 

    public static XXX KEY1 = Constants1.KEY1; 
    public static XXX KEY2 = Constants1.KEY2; 
    public static XXX KEY3 = Constants1.KEY3; 

    // ... 
    public static XXX KEY2000 = Constants2.KEY2000; 

    // Nested class holding 1000 constants 
    private static class Constants1 extends SomeBaseClass { 
    KEY1 = init(...); 
    KEY2 = init(...); 
    KEY3 = init(...); 
    // ... 
    } 

    // Nested class holding the next 1000 constants 
    private static class Constants2 extends SomeBaseClass { 
    // ... 
    KEY2000 = init(...); 
    } 

    // Keep generating nested classes for more constants... 
    private static class Constants3 ... {} 
} 
7

Una opción sería utilizar la herencia - tener una serie de clases Constants1, Constants2, ..., ConstantsN que todos definen las constantes, a continuación, tienen cada uno hereda de la anterior. La clase final Constants puede heredar directamente de la última de ellas. Esto también le permite marcar todo final.

Por curiosidad, ¿cómo terminaste con un archivo tan grande que no podías ajustar el código de inicialización en el límite de 64 KB?

Espero que esto ayude!

+0

Hmm, sí, eso sería una solución válida, un buen pensamiento. También podría colocar todas las constantes en las interfaces y dejar que 'Constants' las implemente todas ... –

+0

Acerca de su pregunta agregada, la respuesta está en los comentarios ... –

+1

También puede hacer esto con clases anidadas, que le permitiría poner todo en un solo archivo fuente. –

0

¿No funcionaría? NO. Vea los comentarios de por qué este tipo de respuesta no resolverá el problema.

Te permitiría mantener las variables estáticas finales y sería más fácil de autogenerar. Sin embargo, java colapsa todos los bloques estáticos de init en un bloque static init gigante y, por lo tanto, el problema no se resuelve.

public class Constants extends SomeBaseClass { 

    // init() is defined in some base class... 
    public static final XXX KEY1 ; 
    static 
    { 
     KEY1 = init(...); 
    } 
    public static final XXX KEY2 ; 
    static 
    { 
     KEY2 = init(...); 
    } 
    public static final XXX KEY3 ; 
    static 
    { 
     KEY3 = init(...); 
    } 

    // ... 

} 
+0

Ya había habido una respuesta como esa (mientras tanto, eliminada). Parece que una clase de código de bytes solo tiene un inicializador estático. El compilador combina todas las declaraciones de inicialización con una única, creo que –

+0

. Es una pena. ¿Pasaría lo mismo si usaras una enumeración? Desventajas XXX tiene que ser de la misma clase y tendrías que volver a trabajar el código para que init() sea una llamada al constructor enum. – emory

+0

No puedo usar una enumeración. El tipo de mundo real 'XXX' tiene parámetros de tipo genérico ...: -/Pero me imagino que bajo las capuchas, las enums comparten la misma lógica de inicializador estático con clases regulares ... –

-1

Puede tener tantos bloques de inicialización estática como desee.

+0

Es lo mismo que la respuesta de [emory] (http://stackoverflow.com/a/10842759/521799) ... –

Cuestiones relacionadas