2012-08-27 26 views
5

Mientras refacturaba un código tropecé con esta rareza. Parece imposible controlar la propiedad strictfp para un inicializador sin afectar a toda la clase. Ejemplo:¿Cómo hacer un bloque de inicializador (estático) strictfp?

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 
    } 

} 

Desde el JLS, Section 8.1.1.3 deduzco que el inicializador sería strictfp si sería declarada la clase utilizando el modificador strictfp. Pero también dice que tiene todos los métodos implícitamente strictfp:

El efecto del modificador strictfp es hacer todo flotador o expresiones dobles dentro de la declaración de la clase (incluidos dentro de los inicializadores de variables, inicializadores de instancia, inicializadores estáticos, y constructores) sea explícitamente FP-estricto (§15.4).

Esto implica que todos los métodos declarados en la clase, y todos los tipos anidados declarados en la clase, son implícitamente strictfp.

Entonces, el modificador no se acepta para el inicializador estático, y cuando se aplica a toda la clase, todo se vuelve strictfp? Como no hay opuesto a la palabra clave strictfp, esto es imposible de lograr.

Así que, ¿estoy jodido por usar un método estático para mantener el cuerpo del bloque de inicialización para lograr un control preciso sobre el rigidez estricta?

+0

¿Por qué hacer que el bloque de inicialización llame a un método estático strictfp es un problema? –

+1

¡Usa una clase de ayuda! (Llame al método de clase auxiliar en su inicializador estático). – EthanB

+0

Sí. Sí. Sí. Pero no veo mucho problema si haces que el método sea 'privado'. Si bien sería mejor asignar el modificador a bloques (tal vez con cierres esto vendrá) los métodos 'privados' son para tales implementaciones internas. Así que "jodido" es demasiado duro para mí. "Forzado" lo describiría mejor para mí. –

Respuesta

0

Uso de los requisitos de que:

  • el código de inicialización se llama una vez,
  • el método MyClass.myMethod es no estricto de punto flotante,
  • la API de la clase no es "lleno de basura" con los métodos,
  • y la inicialización de código es estricta de punto flotante

... esto será suficiente:

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 
    } 
} 

Si se piensa en los miembros estáticos de una clase como objetos en un objeto Singleton separada, el ejemplo anterior parecerá natural. Creo que esto juega muy bien con el Single Responsibility Principle.

+0

Veo, simplemente * oculta * el código del inicializador en otra clase. Aunque me hubiera gustado evitar tener otra clase, esta parece ser la alternativa más limpia. – Durandal

+0

[Ocultamiento de información] (http://en.wikipedia.org/wiki/Information_hiding) ¡Para ganar! – EthanB

+0

¿No podrías simplemente convertirlo en un método privado? – immibis

Cuestiones relacionadas