Java 8 comenzó a aparecer, trayendo una nueva característica: usar la expresión de lambda (JSR-335) para la programación funcional. Hoy vamos a discutir parte de Lambda: Extensión virtual, también conocida como Método de Defensor. Esta característica le permite implementar el método para proporcionar métodos en la definición de interfaz. Por ejemplo, puede definir un método para las interfaces existentes (como la lista y el mapa) para que otros desarrolladores no necesiten volver a implementar estos métodos, que es un poco como abstracto, pero en realidad es una interfaz. Por supuesto, Java 8 es teóricamente compatible con las bibliotecas existentes.
El método de extensión virtual trae múltiples características de herencia a Java. Quizás pueda ver la sombra de la herencia múltiple a través de esta característica. Pero aún puede simular la herencia del estado de instancia. Describiré la herencia del estado a través de la mezcla en el próximo artículo en detalle.
¿Qué se mezcla en mixin?
La mezcla es una clase abstracta de una combinación. Por ejemplo, si tiene una clase para indicar "caballo", puede instanciar esta clase para crear un ejemplo de "caballo", y luego expandirla heredando como "garaje" y "jardín".
Val myhouse = casa nueva con garaje con jardín
De la herencia de mezcla no es una especificación específica, este es solo un método que se utiliza para agregar varias funciones a las categorías existentes. En OOP, con Mixin, tienes la legibilidad de la clase a través de ella.
Por ejemplo, hay un método de mezcla en el módulo SocketServer de Python.
Class ForkingPserver (FORKINGMIXIN, UDPSERVER): PassClass FORKINGTCPSERVER (FORKINGMIXIN, TCPSERVER): PASS Class ThreadingUdPserver (ThreadMixin): PassClass ThreadingTcPserver (ThreadingMixin, TCPserver): PassS Pass
¿Qué es un método de extensión virtual?
Java 8 presentará el concepto de extensión virtual, también llamado Método de Defensor Público.
VEM tiene como objetivo proporcionar el método predeterminado para la interfaz Java. Una tercera biblioteca de tercera parte como Hibernate no necesita repetir todos los métodos de estas API de colección porque ha proporcionado algunos métodos predeterminados.
El siguiente es un ejemplo de cómo definir el método en la interfaz:
Public Interface Collection <T> se extiende iterable <t> {<r> colección <r> filtro (predicada <t> p) predeterminada {colecciones de retorno.
Simulación mixta de Java 8
Ahora llegamos a lograr un efecto mixto a través de VEM, pero la advertencia de antemano es: ¡no use en el trabajo!
La siguiente implementación no es segura de un hilo, y puede haber un problema de fuga de memoria, que depende de los métodos hashcode e equivale a los métodos que definió en la clase.
En primer lugar, definimos una definición de un método (bean de estado simulado) y proporcionamos método:
Interfaz pública switchableMixin {boolean isActivated () predeterminado {return switchables.IsActivated (this);} void setActivated (actividad booleana) falla {switchables.setActivated (this, activado);}}
Luego definimos una clase de herramientas que contiene una instancia de mapa para guardar la asociación de instancias y estado.
Public Final Class Switchables {Mapa final estático privado <SwitchableMixin, switchEntEdEvicestate> switch_states = new Hashmap <() (); Actividad;} public static void setActivated (dispositivo switchableMixIn, boolean activado) {switchEndEdEvicestate = switch_states.get (dispositivo); .Activated = activado;} Clase estática privada SwitchEndEdEvicestate {private boolean activado;}}
Aquí hay un caso de uso que destaca la herencia del estado:
Dispositivo de clase estática privada {} La clase estática privada Devicea extiende el dispositivo implementa switchableMixin {} Device de clase estática privada B extiende el dispositivo Impleter SwitchableMixin {}
"Cosas completamente diferentes"
La implementación anterior parece ser normal, pero el arquitecto de lenguaje Java de Oracle, Brian Goetz, me hizo una pregunta de que la implementación actual no puede funcionar (suponiendo que se haya resuelto la seguridad de los subprocesos y la fuga de memoria)
Interfaz FakeBrokenMixin {mapa estático <falsebrokenmixin, string> backingmap = colecciones. put (this, nombre);}} interfaz X extiende Runnable, falsebrokenmixin {} x makex () {return () -> {system.println ("x");}; ();
¿Qué resultado adivinará que se mostrará este código después de la ejecución?
Solución de duda
A primera vista, no hay problema con este código de implementación. X es una interfaz que contiene solo un método, porque GetName y SetName ya tienen la definición predeterminada, pero el método Ejecutar de la interfaz Runable no está definido. Implementación del método de ejecución. Por lo tanto, el resultado que desea este programa después de la ejecución es:
X1x2
Si elimina la llamada del método GetName, entonces el resultado de la ejecución se convierte en:
Mytest $ 1@30ae8764mytest $ 1@123acf34
Estas dos líneas muestran que la ejecución del método Makex proviene de dos instancias diferentes, y en este momento, se genera el actual OpenJDK 8 (aquí uso OpenJDK 8 24.0-B07).
En cualquier caso, el OpenJDK 8 actual no refleja el comportamiento final de Java 8.
X2x2
Si no llama al método GetName, se mostrará:
Mytest $ $ lambda $ 1@5506d4eamytest $ $ lambda $ 1@5506d4ea
Cada método de llamado MAKEX parece ser una instancia de solteros de la misma clase interna anónima.
Porque durante la compilación, la expresión de Lambda no se sometió a una traducción completa. Esta instrucción contiene toda la metainformación necesaria sobre la expresión de LABDA en tiempo de ejecución. Incluyendo el nombre del método, el tipo de entrada y salida, y un método llamado Bootstrap. El método Bootstrap se utiliza para definir la instancia de recibir este método.
Volver a la pregunta en este momento, la expresión de lambda se convirtió en un método estático privado, () -> {System.out.println ("x");} fue transferido a mytest:
Private static void lambda $ 0 () {system.out.println ("x");}
Si usa el parámetro-Private con el dispositivo de contracompilación Javap y puede ver este método, también puede usar el parámetro -c para ver una conversión más completa.
Cuando ejecuta el programa, JVM llama al método MetaFactory Lambda para tratar de explicar las instrucciones Invokedynamic. En nuestro ejemplo, cuando el MAKEX se considera por primera vez, el método metafactorial de Lambda genera una instancia de una x y vincula dinámicamente el método de ejecución al método Lambda $ 0. En la memoria, por lo que la instancia de su segunda llamada es la misma que la primera vez.
¿Lo reparó? ¿Hay una solución?
No hay reparación directa o solución a este problema. Aunque el programa Java 8 de Oracle predeterminado-xdlambdatomethod, debido a que este parámetro no forma parte de la especificación JVM, la implementación de diferentes proveedores y JVM es diferente. Para una expresión de Lambda, lo único que puede esperar es implementar su método de interfaz en la clase.
Otros métodos
Hasta ahora, aunque nuestra imitación de mixin no puede ser compatible con Java 8, todavía es posible agregar múltiples servicios a través de múltiples herencias y citas para existir. Este método es el patrón de campo virtual (modo de campo virtual).
Así que eche un vistazo a nuestro conmutable.
interfaz conmutable {boolean isactive ();
Necesitamos una interfaz conmutable y proporcionamos un método de abstracción adicional para volver a la implementación conmutable. El método integrado contiene la definición predeterminada.
Public Interface SwitchableView extiende {switchable getSwitchable ();
A continuación, creamos una implementación conmutable completa:
Public Class SwitchableImpl implementa Switchable {private boolean activo;
Este es un ejemplo de nuestro modo de campo virtual:
Public Class Device {} Public Class Devicea extiende el dispositivo SwitchableView {private switchable switchableImpl (); Switchable getSwitchable () {return switchable;}}
en conclusión
En este artículo, utilizamos dos métodos para agregar múltiples servicios a través del método de expansión virtual de Java 8. El primer método utiliza un mapa para almacenar el estado de instancia. Otro método es usar un modo de campo virtual para devolver el ejemplo de implementación final a través de un recibo abstracto. El segundo método es más independiente y más seguro.
El método de extensión virtual es la nueva característica de Java.