vez together implement and java extends implements strictfp

java - together - Comportamiento de la palabra clave strictfp con la implementación/extensión de una interfaz/clase



java public class extends (2)

JLS strictfp Interfaces especifica que:

El efecto del modificador strictfp es hacer que todas las expresiones flotantes o dobles dentro de la declaración de interfaz sean explícitamente FP-estrictas (§15.4).

Esto implica que todos los tipos anidados declarados en la interfaz son implícitamente estrictos.

Y JLS strictfp Clases :

El efecto del modificador strictfp es hacer que todas las expresiones flotantes o dobles dentro de la declaración de interfaz sean explícitamente FP-estrictas (§15.4).

Esto implica que todos los métodos declarados en la interfaz, y todos los tipos anidados declarados en la interfaz, son implícitamente estrictos.

De esos dos párrafos, no hay ninguna indicación del comportamiento de strictfp al implementar / extender una interfaz / clase declarada con el modificador de strictfp .

Después de buscar encontré una buena explicación del uso de la palabra clave strictfp Use el modificador strictfp para la consistencia del cálculo de punto flotante en todas las plataformas , y especifica que:

El comportamiento estricto no es heredado por una subclase que extiende una superclase estricta de FP. Un método de anulación puede elegir independientemente ser estricto de FP cuando el método anulado no lo es, o viceversa.

Y añade:

strictfp el comportamiento de la palabra clave strictfp mientras extendía la clase declarada con la palabra clave strictfp y es cierto: el comportamiento strictfp no es heredado por las clases que extienden la clase, pero el problema es que al implementar una interfaz declarada con la palabra clave strictfp no es correcto: No heredado por las clases que implementan la interfaz.

¿Puede alguien explicarme el comportamiento correcto de strictfp con la implementación / extensión de una interfaz / clase declarada con el modificador de strictfp ?


Aquí están los experimentos que hice para investigar tu pregunta. El código a continuación utiliza la api de reflexiones para verificar si el strictfp está declarado o no en varios escenarios.

Conclusiones:

  1. Los métodos abstractos declarados en la interfaz strictfp no serán estrictamente en la clase que implementa la interfaz.
  2. Los métodos predeterminados declarados en la interfaz strictfp serán stricfp en la clase que implementa la interfaz
  3. Los métodos en las clases que implementan la interfaz strictfp no serán automáticamente strictfp
  4. Todos los métodos declarados en las clases internas de la interfaz strictfp tendrán el modificador stricfp

En resumen, si se declara strictfp en la interfaz, entonces todos los códigos no abstractos (métodos predeterminados, clases internas con métodos) son automáticamente strictfp .

Tenga en cuenta que el modificador strictfp no se aplica a los métodos abstractos.

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

La salida del programa: (usando jdk1.8.0_91.jdk en OSX)

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


JLS §15.4 es bastante claro sobre qué expresiones son estrictas de FP y cuáles no.

Si una clase, interfaz o método, X, se declara estrictamente estricta, entonces X y cualquier clase, interfaz, método, constructor, inicializador de instancia, inicializador estático o inicializador de variable dentro de X se dice que es FP-strict.

De ello se deduce que una expresión no es FP-strict si y solo si no es una expresión constante y no aparece en ninguna declaración que tenga el modificador strictfp.

La palabra clave aquí es declaración . Si no hay strictfp modificador strictfp en una declaración de clase, las expresiones dentro de esta clase no serán estrictas de FP, independientemente de las interfaces que implemente esta clase.

Esto corresponde a tus observaciones. Esto también suena razonable desde el punto de vista común; de lo contrario, sería imposible "restablecer" la rigidez de FP de cualquier miembro de una clase, incluidos los miembros recién introducidos. Mirando el código fuente de javac o HotSpot JVM, no encontrará ningún signo de herencia strictfp .