Behavior of strictfp keyword with implementing/extending an interface/class

1.2k views Asked by At

JLS strictfp Interfaces specifies that :

The effect of the strictfp modifier is to make all float or double expressions within the interface declaration be explicitly FP-strict (§15.4).

This implies that all nested types declared in the interface are implicitly strictfp.

And JLS strictfp Classes :

The effect of the strictfp modifier is to make all float or double expressions within the interface declaration be explicitly FP-strict (§15.4).

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

From those two paragraphs there is no indication of the behavior of strictfp while implementing/extending an interface/class declared with strictfp modifier.

After searching I found a good explanation of the usage of strictfp keyword Use the strictfp modifier for floating-point calculation consistency across platforms, and it specifies that :

Strict behavior is not inherited by a subclass that extends a FP-strict superclass. An overriding method can independently choose to be FP-strict when the overridden method is not, or vice versa.

And it adds : enter image description here

I tested the behavior of strictfp keyword while extending class declared with strictfp keyword and it's true : the strictfp behavior is not inherited by classes extending the class, but the problem is while implementing an interface declared with strictfp keyword it's not correct : the strictfp behavior is not inherited by classes implementing the interface.

Can anyone explain me the correct behavior of strictfp with implementing/extending an interface/class declared with strictfp modifier ?

2

There are 2 answers

1
Piotr Reszke On

Here are the experiments I did to investigate your question. The code below uses reflections api to check if the strictfp is declared or not in various scenarios.

Conclusions:

  1. Abstract methods declared in strictfp interface will not be strictfp in the class implementing the interface
  2. Default methods declared in strictfp interface will be stricfp in the class implementing the interface
  3. Methods in classes that are implementing the strictfp interface will not be automatically strictfp
  4. All the methods declared in the inner classes of strictfp interface will have the stricfp modifier

To sum it up - if the strictfp is declared on the interface, then all the non-abstract code - default methods, inner classes with methods - are automatically strictfp.

Please note that the strictfp modifier is not applied to the abstract methods.

import java.lang.reflect.Modifier;

strictfp interface StrictInterface {

    void someInterfaceMethod();

    default void someInterfaceDefaultMethod() {}

    class InnerTest {
        public static void innerMethod() {}
    }
}

class Impl implements StrictInterface {
    @Override
    public void someInterfaceMethod() {}

    public strictfp void someClassMethod() {}

    public void someClassMethod2() {}
}

public class Test {
    public static void main(String argv[]) {

        checkModifiers(Impl.class, "someInterfaceMethod");
        checkModifiers(Impl.class, "someClassMethod");
        checkModifiers(Impl.class, "someClassMethod2");

        checkModifiers(Impl.class.getInterfaces()[0], "someInterfaceDefaultMethod");
        checkModifiers(StrictInterface.InnerTest.class, "innerMethod");
    }
    public static void checkModifiers(Class clazz, String m) {
        try {
            int mod = clazz.getDeclaredMethod(m, new Class[0]).getModifiers();
            String res = m + " modifiers: " + Modifier.toString(mod);
            System.out.println(res);
        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }
}

The output of the program: (using jdk1.8.0_91.jdk on OSX)

someInterfaceMethod modifiers: public
someClassMethod modifiers: public strictfp
someClassMethod2 modifiers: public
someInterfaceDefaultMethod modifiers: public strictfp
innerMethod modifiers: public static strictfp
2
apangin On

JLS §15.4 is pretty clear about which expressions are FP-strict, and which are not.

If a class, interface, or method, X, is declared strictfp, then X and any class, interface, method, constructor, instance initializer, static initializer, or variable initializer within X is said to be FP-strict.

It follows that an expression is not FP-strict if and only if it is not a constant expression and it does not appear within any declaration that has the strictfp modifier.

The keyword here is declaration. If there is no strictfp modifier in a class declaration, the expressions within this class will not be FP-strict, no matter what iterfaces this class implements.

This corresponds to your observations. This also sounds reasonable from the common sence; otherwise it would be impossible to 'reset' FP-strictness from any member of a class, including newly introduced members. Looking at javac or HotSpot JVM source code you won't find any sign of strictfp inheritance.