2016-08-31 2 views
14

JLS strictfp Interfaces указует, что:Поведения strictfp ключевого слова с реализацией/расширяет интерфейс/класса

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

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

И JLS strictfp Classes:

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

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

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

После поиска я нашел хорошее объяснение использования strictfp ключевого слова Use the strictfp modifier for floating-point calculation consistency across platforms, и это указывает, что:

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

И добавляет: enter image description here

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

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

+0

«Я тестировал поведение ключевого слова strictfp при расширении класса, объявленного с помощью ключевого слова strictfp, и это правда: поведение strictfp не наследуется классами, расширяющими класс». Вопрос в том, как вы его протестировали? Я предполагаю, что это правда, поскольку (из официальных документов) весь класс не будет strictfp - только методы из интерфейса.В любом случае - как вы провели тест? –

+0

Мне кажется, что эта часть неверна «Весь код в любом классе, который реализует интерфейс». Будет ли это наследование временем компиляции или временем загрузки? В других сценариях ключевое слово применяется строго в одном исходном файле '.java', и эффект содержится в одном или нескольких файлах продукта .class. –

+0

@PiotrR Что я имею в виду при тестировании, так это то, что я выполнил несколько случайных примеров, которые охватывают несколько применений 'strictfp' с интерфейсом, методами, конструкторами и классами, а с помощью команды' javap -c' я смог исследовать содержимое сгенерированного кода и посмотреть, наследуется ли поведение 'strictfp' реализованными и расширенными классами. –

ответ

7

Вот эксперименты, которые я сделал для расследования вашего вопроса. В приведенном ниже коде используются рефлексы 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); 
     } 
    } 
} 

Выход программы: (с использованием 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 
+0

Спасибо, ваш код облегчает расследование сгенерированного кода и проверяет, наследуется ли поведение 'strictfp' или нет. –

0

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

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

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

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

Это соответствует вашим наблюдениям. Это также звучит разумно из общего положения; в противном случае было бы невозможно «сбросить» FP-строгость от любого члена класса, включая вновь введенных членов. Рассматривая javac или исходный код JSM HotSpot, вы не найдете никаких признаков strictfp наследования.

+0

Для меня это определение было не очень интуитивным. Я не ожидал, что весь класс будет strictfp, потому что он реализует интерфейс strictfp, НО я не знал, будут ли абстрактные методы, объявленные в интерфейсе, strictfp в классе реализации. Формулировка в JLS 15.4 может быть улучшена. –

Смежные вопросы