18

JLS strictfp 接口指定:

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

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

JLS strictfp 类

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

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

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

经过搜索,我找到了一个很好的解释strictfp关键字的用法使用 strictfp 修饰符实现跨平台的浮点计算一致性,它指定:

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

它补充说: 在此处输入图像描述

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

谁能解释我strictfp实现/扩展使用strictfp修饰符声明的接口/类的正确行为?

4

2 回答 2

9

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

结论:

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

总结一下——如果在strictfp接口上声明了,那么所有的非抽象代码——默认方法、带有方法的内部类——都是自动的strictfp

请注意,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
于 2016-09-19T11:29:02.457 回答
1

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

如果一个类、接口或方法 X 被声明为 strictfp,那么 X 和 X 中的任何类、接口、方法、构造函数、实例初始化器、静态初始化器或变量初始化器都被称为 FP-strict。

因此,表达式不是 FP-strict 当且仅当它不是常量表达式并且它没有出现在任何具有 strictfp 修饰符的声明中。

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

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

于 2016-09-20T08:34:25.523 回答