6

While refactoring some code I stumbled over this oddity. It seems to be impossible to control the strictfp property for an initializer without affecting the entire class. Example:

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
    }

}

From the JLS, Section 8.1.1.3 I gather that the initializer would be strictfp if the class would be declared using the strictfp modifier. But it also says it makes all methods implicitly strictfp:

The effect of the strictfp modifier is to make all float or double expressions within the class declaration (including within variable initializers, instance initializers, static initializers, and constructors) be explicitly FP-strict (§15.4).

This implies that all methods declared in the class, and all nested types declared in the class, are implicitly strictfp.

So, the modifier is not accepted for the static initializer, and when applied to the entire class, everything becomes strictfp? Since there is no opposite to the strictfp keyword, this is impossible to achieve?

So, am I screwed to use a static method to hold the body of the initializer block to achieve precise control over strictfp'dness?

Durandal
  • 19,919
  • 4
  • 36
  • 70
  • Why is making the initializer block call a static strictfp method a problem? – Alan Stokes Aug 27 '12 at 16:10
  • 1
    Use a helper class! (Call the helper-class method in your static initializer.) – EthanB Aug 27 '12 at 17:44
  • Yes. Yes. Yes. But I don't see much of a problem if you make the method `private`. While it would be nicer to assign the modifier to blocks (maybe with closures this will come) `private` methods are for such internal implementations. So "screwed" is too harsh for me. "Forced" would describe it better for me. – Hauke Ingmar Schmidt Aug 27 '12 at 20:17
  • is there any particular reason why you need it in a static block? – Woot4Moo Aug 28 '12 at 19:01
  • @Woot4Moo Well, I think its clearer to initialize a static table in a static initializer than having a private static method that does the work (it doesn't litter the namespace of the class and it makes it impossible to call the initialized multiple times). So I think an initializer block is logically the mechanism to use. – Durandal Aug 29 '12 at 16:31
  • @EthanB I don't see the specific motivation for suggesting a helper *class* here. I *could* put the initialization in a static method just fine (see previous comment why that isn't my immediate choice), so what would I gain by using a helper class? – Durandal Aug 29 '12 at 16:33
  • I think it's dependent on whether you consider static members part of a separate class. I posted a tiny example/answer. – EthanB Aug 29 '12 at 17:47

1 Answers1

1

Using the requirements that:

  • the initialization code is called once,
  • the MyClass.myMethod method is non-strict floating-point,
  • the class API is not "littered" with methods,
  • and the initialization code is strict floating-point

... this will suffice:

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

If you think of the static members of a class as objects in a separate, singleton object, the above example will seem natural. I think this plays very nicely with the Single Responsibility Principle.

EthanB
  • 4,239
  • 1
  • 28
  • 46
  • I see, you simply *hide* the initializer code in another class. Although I would have liked to avoid having another class, this seems to be the cleanest alternative. – Durandal Aug 31 '12 at 10:39
  • [Information hiding](http://en.wikipedia.org/wiki/Information_hiding) For the Win! – EthanB Aug 31 '12 at 13:54
  • Couldn't you just make it a private method? – user253751 Aug 19 '14 at 03:30
  • You certainly could. (In his comments, the OP didn't want to "litter the namespace of the class" and wanted to "[make] it impossible to call the initializer multiple times". Hence this solution.) – EthanB Aug 19 '14 at 12:36