Me enseñaron que la interfaz Marker en Java es una interfaz vacía y se utiliza para indicar al compilador o JVM que los objetos de la clase que implementan esta interfaz deben tratarse de una manera especial, como la serialización, la clonación, etc.
Pero últimamente he aprendido que en realidad no tiene nada que ver con el compilador o la JVM. Por ejemplo, en el caso de Serializable
la interfaz del método writeObject(Object)
de ObjectOutputStream
hace algo como instanceOf Serializable
para detectar si las implementa la clase Serializable
y lanza NotSerializableException
en consecuencia. Todo se maneja en el código y esto parece ser un patrón de diseño, por lo que creo que podemos definir nuestras propias interfaces de marcador.
Ahora mis dudas:
¿Es incorrecta la definición de una interfaz de marcador mencionada anteriormente en el primer punto? ¿Cómo podemos definir una interfaz de marcador entonces?
Y en lugar de usar el
instanceOf
operador, ¿por qué el método no puede ser algowriteObject(Serializable)
así como para que haya una verificación de tipo en tiempo de compilación en lugar de tiempo de ejecución?¿Cómo son las anotaciones mejores que las interfaces de marcador?
fuente
Serializable
como una anotación no tiene sentido y@NonNull
como una interfaz no tiene sentido. Yo diría: las anotaciones son marcadores + metadatos. Por cierto: Forefunner of Annotations fue XDoclet, nacido en Javadoc, asesinado por Annotations.Respuestas:
writeObject(Serializable)
así como para que haya una verificación de tipo en tiempo de compilación ? Esto le permite evitar contaminar su código con el nombre de la interfaz del marcador cuandoObject
se necesita un "plano ". Por ejemplo, si crea una clase que necesita ser serializable y tiene miembros de objeto, se vería obligado a realizar la conversión o hacer sus objetosSerializable
en tiempo de compilación. Esto es inconveniente, porque la interfaz no tiene ninguna funcionalidad.fuente
writeObject
es privado, eso significa que, por ejemplo, una clase no tiene que llamar a la implementación de la superclaseCloneable
que no esté claro si se trata de una biblioteca o un tratamiento JVM de la instancia que está alterada.No es posible hacer cumplir
Serializable
elwriteObject
porque los niños de la clase serializable no pueden ser serializable, pero sus casos puede ser posterior upcasted a la clase padre. Como resultado, mantener una referencia a algo no serializable (comoObject
) no significa que la instancia referida no se pueda serializar realmente. Por ejemplo enla clase padre (
Object
) no es serializable y se inicializaría utilizando su constructor sin parámetros. El valor al que hace referenciax
,String
es serializable y la sentencia condicional correría.fuente
Lo anterior comenzó como una copia de una publicación de blog, pero ha sido ligeramente editado para gramática.
fuente
He hecho una demostración simple para resolver la duda no 1 y 2:
Tendremos una interfaz móvil que implementará
MobilePhone.java
Class y una clase másLandlinePhone.java
que NO implementará la interfaz móvilNuestra interfaz de marcador:
LandLinePhone.java
yMobilePhone.java
Nuestra clase de excepción personalizada: paquete com;
Nuestra clase de Prueba:
TestMArkerInterface.java
Ahora cuando ejecutamos la clase principal:
Entonces, cualquier clase implementa una interfaz de marcador
Movable
pasará la prueba; de lo contrario, se mostrará un mensaje de error.Esta es la forma en
instanceOf
que se realiza la verificación del operador para Serializable , Cloneable , etc.fuente
La interfaz de marcador a / A, como su nombre indica, existe solo para notificar a cualquier cosa que sepa sobre ella que una clase declara algo. Cualquier cosa puede ser las clases JDK para la
Serializable
interfaz, o cualquier clase que escriba usted mismo para una personalizada.b / Si es una interfaz de marcador, no debe implicar la existencia de ningún método; sería mejor incluir el método implícito en la interfaz. Pero puede decidir diseñarlo como desee si sabe por qué lo necesita
c / Hay poca diferencia entre una interfaz vacía y una anotación que no utiliza ningún valor o parámetro. Pero la diferencia está ahí: una anotación puede declarar una lista de claves / valores que serán accesibles en tiempo de ejecución.
fuente
a. Siempre los he visto como un patrón de diseño y nada JVM-Special. He usado ese patrón en varias situaciones.
C. Creo que usar Anotaciones para marcar algo es una mejor solución que usar interfaces de marcador. Simplemente porque las interfaces están en primer lugar destinadas a definir interfaces comunes de tipos / clases. Son parte de la jerarquía de clases.
Las anotaciones están destinadas a proporcionar metainformaciones al código, y creo que ese marcador son metainformaciones. Entonces son exactamente para ese caso de uso.
fuente
No tiene nada que ver (necesariamente) con la JVM y los compiladores, tiene algo que ver con cualquier código que esté interesado y esté probando una interfaz de marcador determinada.
Es una decisión de diseño y se hace por una buena razón. Ver la respuesta de Audrius Meškauskas.
Con respecto a este tema en particular, no creo que sea una cuestión de ser mejor o peor. La interfaz del marcador está haciendo lo que se supone que debe hacer bien.
fuente
El objetivo principal de las interfaces de marcadores es crear tipos especiales donde los tipos en sí mismos no tienen un comportamiento propio.
Aquí, el método save asegura que solo se guarden los objetos de las clases que implementan la interfaz MarkerEntity, para otros tipos se lanza InvalidEntityFoundException. Entonces, la interfaz de marcador MarkerEntity está definiendo un tipo que agrega un comportamiento especial a las clases que lo implementan.
Aunque las anotaciones también se pueden usar ahora para marcar clases para algunos tratamientos especiales, las anotaciones de marcador son un reemplazo para el patrón de nomenclatura, no para las interfaces de marcador.
Pero las anotaciones de marcador no pueden reemplazar completamente las interfaces de marcador porque; Las interfaces de marcador se utilizan para definir el tipo (como ya se explicó anteriormente) donde las anotaciones de marcador no.
Fuente para el comentario de la interfaz del marcador
fuente
En primer lugar, diría que Serializable y Cloneable son malos ejemplos de interfaces de marcadores. Claro, son interfaces con métodos, pero implican métodos, como
writeObject(ObjectOutputStream)
. (El compilador creará unwriteObject(ObjectOutputStream)
método para usted si no lo anula, y todos los objetos ya lo tienenclone()
, pero el compilador volverá a crear unclone()
método real para usted, pero con advertencias. Ambos son casos extraños que realmente no son buenos ejemplos de diseño).Las interfaces de marcador se usan generalmente para uno de dos propósitos:
1) Como atajo para evitar un tipo excesivamente largo, lo que puede suceder con muchos genéricos. Por ejemplo, supongamos que tiene la firma de este método:
Eso es desordenado y molesto de escribir, y lo más importante, difícil de entender. Considere esto en su lugar:
Entonces su método se ve así:
No solo es más claro, sino que ahora puede Javadoc la interfaz Widget, y también es más fácil buscar todas las ocurrencias en su código de Widget.
2) Las interfaces de marcador también se pueden utilizar para evitar la falta de tipos de intersección de Java. Con una interfaz de marcador, puede requerir que algo sea de dos tipos diferentes, como en la firma de un método. Digamos que tiene algún widget de interfaz en su aplicación, como lo describimos anteriormente. Si tiene un método que requiere un Widget que también le permite iterar sobre él (está ideado, pero trabaje conmigo aquí), su única buena solución es crear una interfaz de marcador que extienda ambas interfaces:
Y en tu código:
fuente
Serializable
oCloneable
. Puede verificarlo inspeccionando sus archivos de clase. Además, la creación de "interfaces de acceso directo" no es de lo que se trata la interfaz de marcador. Y es una práctica de codificación realmente mala, ya que requeriría crear clases de implementación adicionales para cumplir con las interfaces adicionales. Por cierto, Java tiene tipos de intersección desde hace una década. Aprenda sobre genéricos ...Si una interfaz no contiene ningún método y, al implementar esa interfaz, nuestro objeto tendrá alguna habilidad, este tipo de interfaces se denominan interfaces marcadoras.
fuente