Поведение ключевого слова strictfp с реализацией / расширением интерфейса / класса

JLS strictfp Interfaces указывает, что:

Эффект модификатора strictfp заключается в том, чтобы сделать все выражения с плавающей запятой или двойные выражения в объявлении интерфейса строго FP-строгими (§15.4).

Это подразумевает, что все вложенные типы, объявленные в интерфейсе, неявно строгие.

И JLS строгие классы:

Эффект модификатора strictfp заключается в том, чтобы сделать все выражения с плавающей запятой или двойные выражения в объявлении интерфейса строго FP-строгими (§15.4).

Это подразумевает, что все методы, объявленные в интерфейсе, и все вложенные типы, объявленные в интерфейсе, являются неявно строгими.

Из этих двух параграфов нет никаких признаков поведения strictfp при реализации / расширении интерфейса / класса, объявленного с strictfp модификатор.

После поиска я нашел хорошее объяснение использования strictfp Ключевое слово Используйте модификатор strictfp для согласованности вычислений с плавающей точкой на разных платформах, и он указывает, что:

Строгое поведение не наследуется подклассом, который расширяет суперкласс строгого FP. Переопределяющий метод может независимо выбрать строгий FP, если переопределяемый метод - нет, или наоборот.

И добавляет:

Я проверил поведение strictfp Ключевое слово при расширении класса объявлено с strictfp Ключевое слово, и это правда: strictfp поведение не наследуется классами, расширяющими класс, но проблема заключается в реализации интерфейса, объявленного с strictfp Ключевое слово это не правильно: strictfp поведение не наследуется классами, реализующими интерфейс.

Может ли кто-нибудь объяснить мне правильное поведение strictfp с реализацией / расширением интерфейса / класса, объявленного с strictfp модификатор?

2 ответа

Вот эксперименты, которые я сделал, чтобы исследовать ваш вопрос. Код ниже использует отражения API, чтобы проверить, strictfp заявлено или нет в различных сценариях.

Выводы:

  1. Абстрактные методы, объявленные в интерфейсе 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);
        }
    }
}

Вывод программы: (используя jdk1.8.0_91.jdk на OSX)

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

В JLS §15.4 довольно ясно, какие выражения строго FP, а какие нет.

Если класс, интерфейс или метод, X, объявлен строгим fp, то X и любой класс, интерфейс, метод, конструктор, инициализатор экземпляра, статический инициализатор или инициализатор переменной в X называются FP-строгими.

Из этого следует, что выражение не является FP-строгим в том и только в том случае, если оно не является константным выражением и не отображается ни в одном объявлении, которое имеет модификатор strictfp.

Ключевое слово здесь - декларация. Если нет strictfp Модификатор в объявлении класса, выражения в этом классе не будут строго FP, независимо от того, какие интерфейсы реализует этот класс.

Это соответствует вашим наблюдениям. Это также звучит разумно из здравого смысла; в противном случае было бы невозможно "сбросить" строгость FP для любого члена класса, включая вновь представленных членов. Смотря на javac или исходный код HotSpot JVM вы не найдете никаких признаков strictfp наследование.

Другие вопросы по тегам