venceras que ordenamiento matriz listas insercion externa enlazadas codigo búsqueda busqueda binario binaria arreglo algoritmo java

que - matriz binaria en java



¿Qué es la compatibilidad binaria en Java? (5)

En resumen, la compatibilidad binaria significa que cuando cambias tu clase, no necesitas recompilar las clases que la usan. Por ejemplo, eliminó o renombró un método público o protegido de esta clase

public class Logger implements Constants { public Logger getLogger(String name) { return LogManager.getLogger(name); } }

de su biblioteca log-1.jar y lanzó una nueva versión como log-2.jar. Cuando los usuarios de su log-1.jar descargan la nueva versión, romperán sus aplicaciones cuando intenten usar el método faltante getLogger (nombre de la cadena).

Y si elimina la interfaz de Constantes (Elemento 17), esto también romperá la compatibilidad binaria, por el mismo motivo.

Pero puede eliminar / renombrar un miembro privado o de un paquete privado de esta clase sin romper la compatibilidad binaria, porque las aplicaciones externas no pueden (o no deben) usarla.

Estaba leyendo Eficaz Java por Joshua Bloch.

En el ítem 17: "Usar interfaces solo para definir tipos", encontré la explicación donde no se recomienda usar interfaces para almacenar constantes. Estoy poniendo la explicación a continuación.

"Lo que es peor, representa un compromiso: si en una versión futura la clase se modifica para que ya no necesite usar las constantes, aún debe implementar la interfaz para garantizar la compatibilidad binaria".

¿Qué significa compatibilidad binaria aquí?

Alguien me puede guiar con un ejemplo en Java para mostrar que el código es compatible con binarios.


Para comprender mejor el concepto, es interesante ver que la compatibilidad binaria NO implica compatibilidad con API , ni viceversa.

API compatible pero NO compatible con binarios : eliminación estática

Versión 1 de la biblioteca:

public class Lib { public static final int i = 1; }

Codigo del cliente:

public class Main { public static void main(String[] args) { if ((new Lib()).i != 1) throw null; } }

Compilar código de cliente con la versión 1:

javac Main.java

Reemplace la versión 1 con la versión 2: elimine la static :

public class Lib { public final int i = 1; }

Recompile solo la versión 2, no el código del cliente, y ejecute java Main :

javac Lib.java java Main

Obtenemos:

Exception in thread "main" java.lang.IncompatibleClassChangeError: Expected static field Lib.i at Main.main(Main.java:3)

Esto sucede porque aunque podemos escribir (new Lib()).i en Java para métodos static y miembros, se compilan en dos instrucciones de VM diferentes según Lib : getstatic o getfield . Esta pausa se menciona en JLS 7 13.4.10 :

Si un campo que no se declaró privado no se declaró estático y se cambió para que se declarara estático, o viceversa, entonces se producirá un error de vinculación, específicamente un IncompatibleClassChangeError, si el campo es utilizado por un binario preexistente que esperaba un campo del otro tipo.

Necesitaríamos recompilar Main con javac Main.java para que funcione con la nueva versión.

Notas:

  • llamar a miembros estáticos de instancias de clase como (new Lib()).i Soy de estilo malo, genera una advertencia y nunca debe hacerse
  • este ejemplo está diseñado porque las primitivas final no estáticas son inútiles: use siempre static final para las primitivas: atributo estático final privado frente a atributo final privado
  • La reflexión podría ser utilizada para ver la diferencia . Pero la reflexión también puede ver campos privados, lo que obviamente conduce a rupturas que no debían contar como rupturas, por lo que no cuenta.

Compatible binario pero NO compatible con API : fortalecimiento de condición previa nula

Versión 1:

public class Lib { /** o can be null */ public static void method(Object o) { if (o != null) o.hashCode(); } }

Versión 2:

public class Lib { /** o cannot be null */ public static void method(Object o) { o.hashCode(); } }

Cliente:

public class Main { public static void main(String[] args) { Lib.method(null); } }

Esta vez, incluso si se vuelve a compilar Main después de actualizar Lib , se lanzará la segunda invocación, pero no la primera.

Esto se debe a que cambiamos el contrato del method de una manera que no es verificable en tiempo de compilación por Java: antes de que pueda tomar el null , ya no más.

Notas:

  • El wiki de Eclipse es una gran fuente para esto: https://wiki.eclipse.org/Evolving_Java-based_APIs
  • Hacer APIs que acepten valores null es una práctica cuestionable
  • es mucho más fácil realizar un cambio que rompe la compatibilidad de API pero no binario que al revés, ya que es fácil cambiar la lógica interna de los métodos

Si en el futuro, deseamos cambiar la interfaz que algunas clases están implementando (por ejemplo, la adición de algunos métodos nuevos).

Si agregamos métodos abstractos (métodos adicionales ), entonces las clases (implementando la interfaz) deben implementar el método adicional, creando restricciones de dependencia y costos generales para realizar lo mismo.

Para superar esto, podemos agregar métodos predeterminados en la interfaz.

Esto eliminará la dependencia para implementar los métodos adicionales.

No necesitamos modificar la clase de implementación para incorporar cambios. Esto se llama como compatibilidad binaria.

Por favor, consulte el siguiente ejemplo:

La interfaz que vamos a utilizar.

//Interface interface SampleInterface { // abstract method public void abstractMethod(int side); // default method default void defaultMethod() { System.out.println("Default Method Block"); } // static method static void staticMethod() { System.out.println("Static Method Block"); } } //The Class that implements the above interface. class SampleClass implements SampleInterface { /* implementation of abstractMethod abstract method, if not implemented will throw compiler error. */ public void abstractMethod(int side) {System.out.println(side*side);} public static void main(String args[]) { SampleClass sc = new SampleClass(); sc.abstractMethod(4); // default method executed sc.defaultMethod(); // Static method executed SampleInterface.staticMethod(); } }

Nota: para obtener información más detallada, consulte los métodos predeterminados


Compatibilidad binaria

La compatibilidad binaria de Java prescribe condiciones bajo las cuales la modificación y la re-compilación de clases no requiere la re-compilación de otras clases importando las clases modificadas. La compatibilidad binaria es un concepto novedoso para el diseño del lenguaje.

La docs.oracle.com/javase/specs/jls/se7/html/jls-13.html describe los cambios binarios compatibles de la siguiente manera:

Un cambio en un tipo es compatible binario con (de manera equivalente, no rompe la compatibilidad con) los binarios preexistentes si los binarios preexistentes que se vincularon previamente sin error continuarán vinculando sin error.


Para hacer que las cosas se vean simples:

Una computadora que puede ejecutar el mismo código binario que se intenta ejecutar en otra computadora se dice que es compatible con binarios. Esto difiere de la compatibilidad del código fuente, donde la recompilación puede ser necesaria.

La compatibilidad binaria es un beneficio importante cuando se desarrollan programas de computadora que se ejecutan en múltiples sistemas operativos.