Markeerinterfaces in Java

1. Inleiding

In deze korte tutorial leren we over markeringsinterfaces in Java.

2. Markeerinterfaces

Een marker-interface is een interface die bevat geen methoden of constanten. Het zorgt voor run-time type informatie over objecten, dus de compiler en JVM hebben aanvullende informatie over het object.

Een marker-interface wordt ook wel een tagging-interface genoemd.

Hoewel markeringsinterfaces nog steeds in gebruik zijn, wijzen ze zeer waarschijnlijk op een codegeur en moeten ze voorzichtig worden gebruikt. De belangrijkste reden hiervoor is dat ze de lijnen over wat een interface vertegenwoordigt, vervagen, aangezien markeringen geen enkel gedrag definiëren. Nieuwere ontwikkeling geeft de voorkeur aan annotaties om enkele van dezelfde problemen op te lossen.

3. JDK-markeerinterfaces

Java heeft veel ingebouwde markeringsinterfaces, zoals Serialiseerbaar, Te klonen, en Afgelegen.

Laten we het voorbeeld nemen van de Te klonen koppel. Als we een object proberen te klonen dat deze interface niet implementeert, gooit de JVM een CloneNotSupportedException. Vandaar dat de Te klonenmarker interface is een indicator voor de JVM dat we de Object.clone () methode.

Op dezelfde manier, wanneer u het ObjectOutputStream.writeObject () methode, de JVM controleert of het object het Serialiseerbaar marker interface. Als dit niet het geval is, wordt een NotSerializableException wordt gegooid. Daarom is het object niet geserialiseerd naar de uitvoerstroom.

4. Aangepaste markeringsinterface

Laten we onze eigen markeringsinterface maken.

We zouden bijvoorbeeld een markering kunnen maken die aangeeft of een object uit de database kan worden verwijderd:

openbare interface Verwijderbaar {}

Om een ​​entiteit uit de database te verwijderen, moet het object dat deze entiteit vertegenwoordigt onze Verwijderbaar marker interface:

public class Entity implementeert verwijderbare {// implementatiedetails}

Laten we zeggen dat we een DAO-object hebben met een methode om entiteiten uit de database te verwijderen. We kunnen onze schrijven verwijderen () methode zodat alleen objecten die onze markeringsinterface implementeren kan worden verwijderd:

public class Shapeensional {// andere DAO-methoden public boolean delete (Object object) {if (! (object instanceof Deletable)) {return false; } // verwijder implementatiedetails retourneren true; }}

Zoals we kunnen zien, we geven een indicatie aan de JVM over het looptijdgedrag van onze objecten. Als het object onze markeringsinterface implementeert, kan het uit de database worden verwijderd.

5. Markeerinterfaces versus annotaties

Door annotaties te introduceren, heeft Java ons een alternatief geboden om dezelfde resultaten te bereiken als de markeringsinterfaces. Bovendien kunnen we, net als markerinterfaces, annotaties toepassen op elke klasse, en we kunnen ze gebruiken als indicatoren om bepaalde acties uit te voeren.

Dus wat is het belangrijkste verschil?

In tegenstelling tot annotaties, laten interfaces ons dat toe profiteer van polymorfisme. Als resultaat kunnen we voeg extra beperkingen toe aan de markeringsinterface.

Laten we bijvoorbeeld een beperking toevoegen die alleen een Vorm type kan uit de database worden verwijderd:

openbare interface Shape {double getArea (); dubbele getCircumference (); }

In dit geval, onze marker-interface, laten we het noemen Verwijderbare vorm, ziet er als volgt uit:

openbare interface DeletableShape verlengt Shape {}

Dan zal onze klas de marker-interface implementeren:

public class Rectangle implementeert DeletableShape {// implementatiedetails}

Daarom alle DeletableShape implementaties zijn ook Vorm implementaties. Duidelijk, we kunnen dat niet doen met annotaties.

Elke ontwerpbeslissing heeft echter afwegingen en polymorfisme kan als tegenargument worden gebruikt tegen markeringsinterfaces. In ons voorbeeld breidt elke klasse zich uit Rechthoek wordt automatisch geïmplementeerd DeletableShape.

6. Markeerinterfaces versus typische interfaces

In het vorige voorbeeld konden we dezelfde resultaten krijgen door onze DAO's aan te passen verwijderen () methode om te testen of ons object een Vorm of niet, in plaats van te testen of het een Verwijderbaar:

public class Shapeensional {// andere DAO-methoden public boolean delete (Object object) {if (! (object instanceof Shape)) {return false; } // verwijder implementatiedetails retourneren true; }}

Dus waarom zou u een markeringsinterface maken als we dezelfde resultaten kunnen bereiken met een typische interface?

Laten we ons voorstellen dat, naast de Vorm type, we willen de Persoon typ ook uit de database. In dit geval zijn er twee opties om dat te bereiken:

De eerste optie is om een ​​extra vinkje toe te voegen aan onze vorige verwijderen () methode om te controleren of het te verwijderen object een exemplaar is van Persoon of niet.

public boolean delete (Object object) {if (! (object instanceof Shape || object instanceof Person)) {return false; } // verwijder implementatiedetails retourneren true; }

Maar wat als we meer typen hebben die we ook uit de database willen verwijderen? Het is duidelijk dat dit geen goede optie is, want dat hebben we gedaan om onze methode voor elk nieuw type te veranderen.

De tweede optie is makende Persoon type implementeren de Vorm koppel, dat fungeert als een markeringsinterface. Maar is een Persoon object echt een Vorm? Het antwoord is duidelijk nee, en dat maakt de tweede optie erger dan de eerste.

Vandaar, hoewel we kunnen dezelfde resultaten bereiken door een typische interface als marker te gebruiken, we zullen eindigen met een slecht ontwerp.

7. Conclusie

In dit artikel hebben we besproken wat marker-interfaces zijn en hoe ze kunnen worden gebruikt. Vervolgens hebben we gekeken naar enkele ingebouwde Java-voorbeelden van dit type interfaces en hoe deze worden gebruikt door de JDK.

Vervolgens hebben we onze eigen markeringsinterface gemaakt en deze afgewogen met behulp van een annotatie. Ten slotte zien we waarom het een goede gewoonte is om in sommige scenario's een markeringsinterface te gebruiken in plaats van een traditionele interface.

Zoals altijd is de code te vinden op GitHub.