setlayout definicion create java java-8 default-method forward-compatibility

definicion - ¿Los métodos predeterminados de Java 8 rompen la compatibilidad de origen?



setlayout jpanel (5)

¿JDK 1.8 no presenta una incompatibilidad directa para el código fuente de Java debido a los métodos predeterminados?

Sí, como te has visto a ti mismo.

¿Es este el primer cambio incompatible hacia adelante?

No. La palabra clave enum Java 5 también se estaba rompiendo porque antes de eso se podían tener variables llamadas que ya no se compilarían en Java 5

¿Se consideró o discutió esto cuando se diseñaron e implementaron métodos predeterminados? ¿Está documentado en alguna parte?

Orcale Java 8 fuente incompatibilidad descripción

¿Se descontó el inconveniente (ciertamente pequeño) frente a los beneficios?

En general, ha sido el caso de que el código fuente de Java ha sido compatible con versiones anteriores. Hasta Java 8, que yo sepa, tanto las clases compiladas como la fuente han sido compatibles con versiones posteriores de JDK / JVM. [Actualización: esto no es correcto, vea los comentarios re ''enum'', etc., a continuación.] Sin embargo, con la adición de métodos predeterminados en Java 8, este parece no ser el caso.

Por ejemplo, una biblioteca que he estado usando tiene una implementación de java.util.List que incluye una List<V> sort() . Este método devuelve una copia del contenido de la lista ordenada. Esta biblioteca, implementada como una dependencia del archivo jar, funcionó bien en un proyecto que se construyó utilizando JDK 1.8.

Sin embargo, más tarde tuve la oportunidad de recompilar la biblioteca usando JDK 1.8 y descubrí que la biblioteca ya no se compila: la clase de implementación de listas con su propio método sort() ahora entra en conflicto con Java 8 java.util.List.sort() método predeterminado El método predeterminado Java 8 sort() ordena la lista en su lugar (devuelve void ); El método sort() mi biblioteca, ya que devuelve una nueva lista ordenada, tiene una firma incompatible.

Entonces mi pregunta básica es:

  • ¿JDK 1.8 no presenta una incompatibilidad directa para el código fuente de Java debido a los métodos predeterminados?

También:

  • ¿Es este el primer cambio incompatible hacia adelante?
  • ¿Se consideró o discutió esto cuando se diseñaron e implementaron métodos predeterminados? ¿Está documentado en alguna parte?
  • ¿Se descontó el inconveniente (ciertamente pequeño) frente a los beneficios?

El siguiente es un ejemplo de algún código que compila y ejecuta en 1.7 y ejecuta en 1.8, pero no compila en 1.8:

import java.util.*; public final class Sort8 { public static void main(String[] args) { SortableList<String> l = new SortableList<String>(Arrays.asList(args)); System.out.println("unsorted: "+l); SortableList<String> s = l.sort(Collections.reverseOrder()); System.out.println("sorted : "+s); } public static class SortableList<V> extends ArrayList<V> { public SortableList() { super(); } public SortableList(Collection<? extends V> col) { super(col); } public SortableList<V> sort(Comparator<? super V> cmp) { SortableList<V> l = new SortableList<V>(); l.addAll(this); Collections.sort(l, cmp); return l; } } }

A continuación se muestra este código que se está compilando (o no) y se está ejecutando.

> c:/tools/jdk1.7.0_10/bin/javac Sort8.java > c:/tools/jdk1.7.0_10/bin/java Sort8 this is a test unsorted: [this, is, a, test] sorted : [this, test, is, a] > c:/tools/jdk1.8.0_05/bin/java Sort8 this is a test unsorted: [this, is, a, test] sorted : [this, test, is, a] > del Sort8*.class > c:/tools/jdk1.8.0_05/bin/javac Sort8.java Sort8.java:46: error: sort(Comparator<? super V>) in SortableList cannot implement sort(Comparator<? super E>) in List public SortableList<V> sort(Comparator<? super V> cmp) { ^ return type SortableList<V> is not compatible with void where V,E are type-variables: V extends Object declared in class SortableList E extends Object declared in interface List 1 error


Al leer este problema, estaba pensando en su solución.
Los métodos predeterminados han resuelto los problemas de compatibilidad con versiones anteriores, pero existirán problemas de compatibilidad con versiones anteriores.
Creo que en lugar de extender las clases existentes, en tales casos, podemos tener nuestras interfaces específicas de la aplicación para agregar un comportamiento deseado a nuestra clase. Podemos implementar esta interfaz específica de la aplicación y usarla.


Irónicamente, se introdujeron métodos predeterminados en las interfaces para permitir que las bibliotecas existentes que usan esas interfaces no se rompan, al tiempo que se introducen nuevas funcionalidades masivas en las interfaces. (compatibilidad con versiones anteriores.)

Pueden surgir conflictos como ese método de sort . Algo para pagar por la funcionalidad adicional. En su caso, también hay algo que investigar (¿deberían utilizarse nuevas funciones en su lugar?).

Las interrupciones de compatibilidad con Java son poco, más en su sistema de mecanografía, que se amplió constantemente. Primero con tipos genéricos y ahora con tipos inferidos de interfaces funcionales. De versión a versión y de compilador a compilador hubo ligeras diferencias.


Podemos dibujar un paralelo con la clase abstracta. Se pretende que una clase abstracta se subclasifique para que se puedan implementar los métodos abstractos. La clase abstracta en sí contiene métodos concretos que invocan los métodos abstractos. La clase abstracta es libre de evolucionar agregando métodos más concretos; y esta práctica puede romper subclases.

Por lo tanto, el problema exacto que describió existía incluso antes de Java8. El problema se manifiesta mucho más en las API de recopilación porque hay muchas subclases en la naturaleza.

Si bien la principal motivación del método predeterminado era agregar algunos métodos útiles a las API de colección existentes sin romper las subclases, tuvieron que ejercer un gran autocontrol de hacerlo demasiado, por temor a romper las subclases. Se agrega un método predeterminado solo si es absolutamente necesario. La verdadera pregunta aquí es por qué List.sort se considera absolutamente necesario. Creo que eso es discutible.

Independientemente de por qué el método predeterminado se introdujo en primer lugar, ahora es una gran herramienta para los diseñadores de API, y debemos tratarlo de la misma manera que los métodos concretos en clases abstractas: deben diseñarse cuidadosamente por adelantado; y los nuevos deben ser introducidos con gran precaución.


¿JDK 1.8 no presenta una incompatibilidad directa para el código fuente de Java debido a los métodos predeterminados?

Cualquier método nuevo en una superclase o interfaz puede romper la compatibilidad. Los métodos predeterminados hacen que sea menos probable que un cambio en una interfaz rompa la compatibilidad. En el sentido de que los métodos predeterminados abren la puerta a agregar métodos a las interfaces, se podría decir que los métodos predeterminados pueden contribuir a una compatibilidad rota.

¿Es este el primer cambio incompatible hacia adelante?

Es casi seguro que no, ya que hemos estado subclasificando clases de la biblioteca estándar desde Java 1.0.

¿Se consideró o discutió esto cuando se diseñaron e implementaron los métodos predeterminados? ¿Está documentado en alguna parte?

Sí, fue considerado. Consulte el documento de Brian Goetz de agosto de 2010 "Evolución de la interfaz a través de métodos de" defensor público " :

  1. Compatibilidad de fuente

Es posible que este esquema pueda introducir incompatibilidades de origen en la medida en que las interfaces de la biblioteca se modifiquen para insertar nuevos métodos que sean incompatibles con los métodos de las clases existentes. (Por ejemplo, si una clase tiene un método xyz () con valor flotante e implementa Collection, y agregamos un método xyz () con valor int a Collection, la clase existente ya no se compilará).

¿Se descontó el inconveniente (ciertamente pequeño) frente a los beneficios?

Antes, cambiar una interfaz definitivamente rompería la compatibilidad. Ahora sí. Pasar de ''definitivamente'' a ''poder'' puede verse de manera positiva o negativa. Por un lado, hace posible agregar métodos a las interfaces. Por otro lado, abre la puerta al tipo de incompatibilidad que viste, no solo con las clases, sino también con las interfaces.

Sin embargo, los beneficios son mayores que los inconvenientes, como se cita en la parte superior del documento de Goetz:

  1. Planteamiento del problema

Una vez publicado, es imposible agregar métodos a una interfaz sin romper las implementaciones existentes. Cuanto más tiempo transcurra desde que se publicó una biblioteca, es más probable que esta restricción cause dolor a sus encargados.

La adición de cierres al lenguaje Java en JDK 7 ejerce una presión adicional sobre las antiguas interfaces de la Colección; Uno de los beneficios más importantes de los cierres es que permite el desarrollo de bibliotecas más potentes. Sería decepcionante agregar una función de idioma que permita mejores bibliotecas y, al mismo tiempo, no extienda las bibliotecas centrales para aprovechar esa función.