6

Ho una classe in possesso di un grande un monte di costanti generati in quanto tale:Come aggirare il limite di dimensione di un initialiser statica in Java quando l'inizializzazione di grandi quantità di costanti

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

Quando il numero di costanti generati è molto alto, questo si traduce in un inizializzatore statico che è maggiore del limite superiore per le dimensioni del metodo Java (cioè> 64kb), provocando un errore del compilatore. Una soluzione è quella di creare diversi "metodi di inizializzazione blocco" per blocchi che possono essere garantiti per produrre meno di 64kb di byte-code, in modo tale che si inseriscono in un metodo:

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

Lo svantaggio di questo è che posso non dichiarare più le costanti come final, perché ora non sono più inizializzate direttamente nell'inizializzatore statico.

La mia domanda è: come posso aggirare la limitazione del compilatore/JVM in modo che sia possibile generare costanti static final?

+0

Come hai fatto a finire in esecuzione in questo problema? Questo codice è generato da un altro file? – templatetypedef

+0

@templatetypedef: questo è un bug reale nel generatore del codice sorgente di [jOOQ] (http://www.jooq.org). Genera chiavi primarie, chiavi univoche e chiavi esterne come oggetti costanti da un database. Sembra che le 2000 chiavi siano troppo per gestire jOOQ: https://groups.google.com/d/topic/jooq-user/2g96fI1Yrj8/discussion –

+0

Potresti usare strati di ereditarietà "fittizi" per questo? Avere una classe base con un nome non pubblico che contiene 1.000 costanti e ha un inizializzatore statico impostato. Quindi una classe derivata che aggiunge altri 1.000, una classe subderived che aggiunge un altro 1,000, ecc.? Solo la classe più derivata sarebbe mai stata utilizzata per qualsiasi scopo tranne che per la derivazione delle altre classi nell'assembly. – supercat

risposta

1

Finalmente sono andato per una soluzione che coinvolge classi nidificate. Questo è stato suggerito in un commento a this answer here dall'utente Loadmaster.classi nidificate hanno due vantaggi:

  • Permettono per nascondere questi dettagli di implementazione soluzione dal mondo esterno per essere private classi nidificate
  • Essi consentono di mantenere costanti final

ma hanno anche uno svantaggio rispetto alla soluzione templatetypedef's:

  • Mi imbatterò nuovamente nello stesso problema con molto lar numeri ger di costanti

In questo momento, però, questa sembra essere la soluzione più adatta:

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 possibilità potrebbe essere quella di utilizzare l'ereditarietà - avere una serie di classi Constants1, Constants2, ..., ConstantsN che tutti definiscono le costanti, quindi hanno ciascuno eredita da quella precedente. La classe finale Constants può quindi ereditare direttamente dall'ultimo di essi. Ciò consente anche di contrassegnare tutto final.

Per curiosità, come sei arrivato a un file così grande da non riuscire ad adattare il codice di inizializzazione al limite di 64 KB?

Spero che questo aiuti!

+0

Hmm, sì, sarebbe una soluzione valida, un pensiero piacevole. Potrei anche posizionare tutte le costanti nelle interfacce e lasciare che i 'Costanti 'li implementino tutti ... –

+0

Informazioni sulla tua domanda aggiunta, la risposta è nei commenti ... –

+1

Potrebbe essere possibile farlo anche con classi nidificate, che ti permetterebbe di mettere tutto in un unico file sorgente. –

0

Non funziona? NO. Vedi i commenti sul perché questo tipo di risposta non risolverà il problema.

Permetterebbe di mantenere le variabili statiche finali e sarebbe più facile da autogenerare. Tuttavia, java collassa tutti i blocchi di init statici in un blocco di init statico gigante e quindi il problema non viene risolto.

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

C'era già stata una risposta del genere (nel frattempo, cancellata). Sembra che una classe byte-code abbia solo un inizializzatore statico. Il compilatore combina tutte le istruzioni di inizializzazione in una sola, penso che sia –

+0

Questo è un peccato. Succederebbe la stessa cosa se usassi un enum? Svantaggi XXX deve essere la stessa classe e bisognerà rielaborare il codice in modo che init() sia una chiamata al costruttore enum. – emory

+0

Non riesco a usare enum. Il tipo di mondo reale 'XXX' ha parametri di tipo generico ...: -/Ma immagino che sotto il cofano, le enumerazioni condividano la stessa logica di inizializzazione statica con classi regolari ... –

-1

Si può avere il maggior numero di blocchi di inizializzazione statica come si desidera.

+0

È lo stesso di [emory's] (http://stackoverflow.com/a/10842759/521799) risposta ... –

Problemi correlati