Поведение ключевого слова strictfp с внедрением/расширением интерфейса/класса
JLS strictfp Интерфейсы определяет, что:
Эффект модификатора strictfp состоит в том, чтобы сделать все float или double выражения в объявлении интерфейса явно FP-строгими (§15.4).
Это означает, что все вложенные типы, объявленные в интерфейсе, неявно строго определены.
И JLS strictfp Классы:
Эффект модификатора strictfp состоит в том, чтобы сделать все float или double выражения в объявлении интерфейса явно FP-строгими (§15.4).
Это означает, что все методы, объявленные в интерфейсе, и все вложенные типы, объявленные в интерфейсе, неявно строго определены.
Из этих двух абзацев нет указания на поведение strictfp
при реализации/расширении интерфейса/класса, объявленного с помощью модификатора strictfp
.
После поиска я нашел хорошее объяснение использования ключевого слова strictfp
Использовать модификатор strictfp для согласования вычислений с плавающей запятой между платформами, и он указывает, что:
Строгое поведение не наследуется подклассом, который расширяет FP-строгий суперкласс. Метод переопределения может независимо выбирать FP-строгий, если переопределенный метод не является, или наоборот.
И добавляет:
![введите описание изображения здесь]()
Я тестировал поведение ключевого слова strictfp
при расширении класса, объявленного с ключевым словом strictfp
, и это правда: поведение strictfp
не наследуется классами, расширяющими класс, но проблема заключается в реализации интерфейса, объявленного с помощью strictfp
Неверное ключевое слово: поведение strictfp
не наследуется классами, реализующими интерфейс.
Может ли кто-нибудь объяснить мне правильное поведение strictfp
с реализацией/расширением интерфейса/класса, объявленного с помощью модификатора strictfp
?
Ответы
Ответ 1
Вот эксперименты, которые я сделал для исследования вашего вопроса. В приведенном ниже коде используются рефлексы api, чтобы проверить, объявлен ли strictfp
или нет в разных сценариях.
Выводы:
- Абстрактные методы, объявленные в формате strictfp, не будут strictfp в классе, реализующем интерфейс
- Стандартные методы, объявленные в строчном интерфейсе, будут stricfp в классе, реализующем интерфейс
- Методы в классах, реализующих строковый интерфейс, не будут автоматически strictfp
- Все методы, объявленные в внутренних классах интерфейса 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
Ответ 2
JLS §15.4 довольно ясно, какие выражения FP-строгие, а какие нет.
Если класс, интерфейс или метод X объявлен strictfp, то X и любой класс, интерфейс, метод, конструктор, инициализатор экземпляра, статический инициализатор или инициализатор переменной в X называется FP-строгое.
Отсюда следует, что выражение не является FP-строгим тогда и только тогда, когда оно не постоянное выражение, и оно не отображается в пределах любого Объявление, имеющее модификатор strictfp.
Ключевое слово здесь Объявление. Если в объявлении класса нет модификатора strictfp
, выражения внутри этого класса не будут FP-строгими, независимо от того, что он реализует в этом классе.
Это соответствует вашим наблюдениям. Это также звучит разумно из общего положения; иначе было бы невозможно "reset" FP-строгость от любого члена класса, включая вновь введенных членов. Рассматривая исходный код javac
или HotSpot JVM, вы не найдете признаков наследования strictfp
.