18

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 ?

Community
  • 1
  • 1
Naruto Biju Mode
  • 2,011
  • 3
  • 15
  • 28
  • "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," The question is - How did you test it? I assume that it's true, as (from the official docs) the whole class will not be strictfp - only the methods from the interface. Anyway - how did you perform the test? – Piotr Reszke Sep 17 '16 at 19:26
  • It sounds to me like this part is wrong `All code in any class that implements the interface`. Would this inheritance occur compile time or load time anyway? In other scenarios, the keyword applies strictly within one `.java` source file and the effect is contained within one or more product `.class` files. – Teemu Ilmonen Sep 19 '16 at 11:21
  • @PiotrR What i mean with testing is that i executed multiple random examples that cover multiple uses of `strictfp` with interface, methods, constructors and classes, and with the help of `javap -c` command i was able to investigate the content of the generated code and see if the behavior of `strictfp` is inherited by implemented and extended classes. – Naruto Biju Mode Sep 19 '16 at 18:44
  • @TeemuIlmonen Yes i think that is true because the `strictfp` can't be found inside the classes that implement the interface declared with `strictfp` keyword. – Naruto Biju Mode Sep 19 '16 at 18:49

2 Answers2

9

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
Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
Piotr Reszke
  • 1,576
  • 9
  • 21
1

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.

apangin
  • 92,924
  • 10
  • 193
  • 247
  • 2
    For me this definition was not very intuitive. I didn't expect the whole class to be strictfp because it implements strictfp interface, BUT I didn't know if abstract methods declared in the interface would be strictfp in the implementing class. The wording in JLS 15.4 could be improved. – Piotr Reszke Sep 20 '16 at 09:44
  • Now it's pretty clear: https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.4 – Dávid Horváth Dec 25 '20 at 11:05