2012-08-27 15 views
5

Durante il refactoring del codice ho inciampato su questa stranezza. Sembra impossibile controllare la proprietà strictfp per un inizializzatore senza influenzare l'intera classe. Esempio:Come rendere strictfp un blocco di inizializzazione (statico)?

public class MyClass { 

    public final static float[] TABLE; 
    strictfp static { // this obviously doesn't compile 
     TABLE = new float[...]; 
     // initialize table 
    } 

    public static float[] myMethod(float[] args) { 
     // do something with table and args 
     // note this methods should *not* be strictfp 
    } 

} 

Dal JLS, Section 8.1.1.3 ho capito che l'inizializzatore sarebbe strictf se la classe sarebbe stato dichiarato utilizzando il modificatore strictf. Ma si dice anche che rende tutti i metodi implicitamente strictf:

L'effetto del modificatore strictf è quello di rendere tutti i float o doppio espressioni all'interno della dichiarazione della classe (anche all'interno inizializzatori variabili, inizializzatori esempio, inizializzatori statici, e costruttori) essere esplicitamente FP-strict (§15.4).

Ciò implica che tutti i metodi dichiarati nella classe e tutti i tipi annidati dichiarati nella classe sono implicitamente strictfp.

Quindi, il modificatore non è accettato per l'inizializzatore statico e quando viene applicato all'intera classe, tutto diventa strictfp? Dal momento che non esiste l'opposto della parola chiave strictfp, è impossibile raggiungerlo?

Quindi, sono avvitato per utilizzare un metodo statico per tenere il corpo del blocco inizializzatore per ottenere un controllo preciso su strictfp'dness?

+0

Perché il blocco di inizializzazione chiama un metodo static strictfp un problema? –

+1

Utilizza una classe di supporto! (Chiama il metodo helper-class nel tuo inizializzatore statico.) – EthanB

+0

Sì. Sì. Sì. Ma non vedo un gran problema se rendi il metodo 'private'. Mentre sarebbe più bello assegnare il modificatore ai blocchi (forse con le chiusure arriverà) i metodi 'private' sono per tali implementazioni interne. Quindi "fregato" è troppo duro per me. "Forzato" lo descriverebbe meglio per me. –

risposta

0

Usando i requisiti che:

  • il codice di inizializzazione viene chiamato una volta,
  • il metodo MyClass.myMethod non è rigida virgola mobile,
  • l'API classe non è "disseminato" con metodi,
  • e l'inizializzazione codice è rigoroso virgola mobile

... questo sarà sufficiente:

class MyClass { 
    //1) initialized/called once 
    public final static float[] TABLE = MyClassInitializer.buildSomething(); 

    public static float[] myMethod(float[] args) { 
    //2) non-strict 
    } 
} 

//3) doesn't "pollute" the MyClass API 
class MyClassInitializer { 
    strictfp [static] float[] buildSomething() { //4) strictfp here or on the class 
    //TODO: return something 
    } 
} 

Se si pensa che i membri statici di una classe come oggetti in un oggetto Singleton separata, l'esempio precedente sembrerà naturale. Penso che questo funzioni molto bene con lo Single Responsibility Principle.

+0

Vedo, è sufficiente * nascondere * il codice inizializzatore in un'altra classe. Anche se mi sarebbe piaciuto evitare di avere un'altra classe, questa sembra essere l'alternativa più pulita. – Durandal

+0

[Nascondere informazioni] (http://en.wikipedia.org/wiki/Information_hiding) Per la vittoria! – EthanB

+0

Non potresti semplicemente renderlo un metodo privato? – immibis

Problemi correlati