严格fp关键字在实现/扩展接口/类时的行为

2022-09-02 22:26:42

JLS strictfp Interfaces 指定:

strictfp 修饰符的作用是使接口声明中的所有浮点表达式或双精度表达式都显式为 FP-strict (§15.4)。

这意味着接口中声明的所有嵌套类型都是隐式 strictfp。

JLS strictfp类

strictfp 修饰符的作用是使接口声明中的所有浮点表达式或双精度表达式都显式为 FP-strict (§15.4)。

这意味着接口中声明的所有方法以及在接口中声明的所有嵌套类型都是隐式 strictfp。

从这两个段落中,没有迹象表明在实现/扩展使用修饰符声明的接口/类时的行为。strictfpstrictfp

搜索后,我发现了关键字用法的很好解释 使用 strictfp 修饰符实现跨平台的浮点计算一致性,并指定:strictfp

严格行为不会由扩展 FP 严格超类的子类继承。当重写的方法不被覆盖时,重写方法可以独立选择 FP 严格,反之亦然。

它补充说:enter image description here

我在扩展用关键字声明的类时测试了关键字的行为,这是真的:行为不是由扩展类的类继承的,但问题是在实现用关键字声明的接口时,它是不正确的:行为不是由实现接口的类继承的。strictfpstrictfpstrictfpstrictfpstrictfp

任何人都可以解释一下实现/扩展用修饰符声明的接口/类的正确行为吗?strictfpstrictfp


答案 1

以下是我为调查您的问题所做的实验。下面的代码使用反射 api 来检查在各种方案中是否声明了 。strictfp

结论:

  1. strictfp 接口中声明的抽象方法在实现接口的类中不会是 strictfp
  2. strictfp 接口中声明的默认方法将在实现接口的类中为 stricfp
  3. 实现 strictfp 接口的类中的方法不会自动成为 strictfp
  4. strictfp 接口的内部类中声明的所有方法都将具有 stricfp 修饰符

总而言之 - 如果在接口上声明,则所有非抽象代码 - 默认方法,带有方法的内部类 - 都是自动的 。strictfpstrictfp

请注意,修饰符不适用于抽象方法。strictfp

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

程序的输出:(在OSX上使用jdk1.8.0_91.jdk)

someInterfaceMethod modifiers: public
someClassMethod modifiers: public strictfp
someClassMethod2 modifiers: public
someInterfaceDefaultMethod modifiers: public strictfp
innerMethod modifiers: public static strictfp

答案 2

JLS §15.4 非常清楚哪些表达式是 FP 严格的,哪些不是。

如果类、接口或方法 X 被声明为 strictfp,则 X 和 X 内的任何类、接口、方法、构造函数、实例初始值设定项、静态初始值设定项或变量初始值设定项都称为 FP 严格。

因此,当且仅当表达式不是常量表达式并且不出现在任何具有 strictfp 修饰符的声明中时,该表达式才不是 FP 严格表达式。

这里的关键字是声明。如果类声明中没有修饰符,则无论此类实现什么迭代,此类中的表达式都不会是 FP 严格的。strictfp

这与您的观察结果相对应。从常识来看,这听起来也是合理的;否则,就不可能从类的任何成员(包括新引入的成员)“重置”FP严格性。查看或HotSpot JVM源代码,您不会发现任何继承的迹象。javacstrictfp


推荐