2012-08-27 25 views
5

Podczas refaktoryzacji kodu natknąłem się na tę dziwność. Wydaje się niemożliwe, aby kontrolować właściwość strictfp dla inicjalizatora bez wpływu na całą klasę. Przykład:Jak zrobić (statyczny) blok inicjalizatora 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 
    } 

} 

Z JLS, Section 8.1.1.3 wnoszę, że inicjator będzie strictfp jeśli klasa będzie zadeklarowane używając modyfikatora strictfp. Ale to też mówi, że sprawia, że ​​wszystkie metody niejawnie strictfp:

Wpływ modyfikatora strictfp jest, aby cały pływak lub wyrażenia podwójne wewnątrz deklaracji klasy (w tym w zmiennych inicjalizatorów, np inicjalizatorów, inicjalizatorów statycznych i konstruktorzy) jawnie FP-strict (§15.4).

Oznacza to, że wszystkie metody zadeklarowane w klasie i wszystkie typy zagnieżdżone zadeklarowane w klasie są niejawnie strictfp.

W związku z tym modyfikator nie jest akceptowany dla inicjalizatora statycznego, a po zastosowaniu do całej klasy wszystko staje się strictfp? Ponieważ nie ma przeciwieństwa słowa kluczowego strictfp, jest to niemożliwe do osiągnięcia?

Tak, czy jestem przykuty, aby użyć statycznej metody przytrzymywania korpusu bloku inicjalizatora w celu uzyskania precyzyjnej kontroli nad restrykcyjnością?

+0

Dlaczego wywołanie bloku inicjalizacyjnego jest metodą statyczną metodą strictfp? –

+1

Użyj klasy pomocnika! (Zadzwoń do metody klasy pomocniczej w inicjalizatorze statycznym.) – EthanB

+0

Tak. Tak. Tak. Ale nie widzę większego problemu, jeśli utworzysz metodę "private". O ile lepiej byłoby przypisać modyfikator do bloków (być może z zamknięciem to przyjdzie), metody "prywatne" są dla takich wewnętrznych implementacji. Tak więc "skręcane" jest dla mnie zbyt surowe. "Zmuszony" opisałby to lepiej dla mnie. –

Odpowiedz

0

Korzystanie wymagania, które:

  • kod inicjalizacji jest wywoływana raz,
  • metoda MyClass.myMethod nie jest ścisłe zmiennoprzecinkową,
  • klasa API nie jest „zaśmiecony” metodami,
  • i inicjalizacja kod jest ścisłe zmiennoprzecinkowych

... to wystarczy:

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

Jeśli uważasz statycznych członkowie klasy jako obiektów w oddzielnym, jednoelementowy obiektu, powyższy przykład może wydawać się naturalne. Myślę, że gra bardzo ładnie z Single Responsibility Principle.

+0

Rozumiem, po prostu * ukrywasz * kod inicjalizacyjny w innej klasie. Chociaż chciałbym uniknąć kolejnej lekcji, wydaje się, że jest to najczystsza alternatywa. – Durandal

+0

[Ukrywanie informacji] (http://en.wikipedia.org/wiki/Wykonywanie informacji) Wygraj! – EthanB

+0

Nie możesz zrobić, że to prywatna metoda? – immibis