Markørgrænseflader i Java

1. Introduktion

I denne hurtige vejledning lærer vi om markørgrænseflader i Java.

2. Markørgrænseflader

En markørgrænseflade er en grænseflade, der har ingen metoder eller konstanter inde i det. Det giver information om kørselstider om objekter, så har compileren og JVM det yderligere oplysninger om objektet.

En markørgrænseflade kaldes også en tagging-grænseflade.

Selvom markørgrænseflader stadig er i brug, peger de meget sandsynligt på en kodelugt og bør bruges omhyggeligt. Hovedårsagen til dette er, at de slører linjerne om, hvad en grænseflade repræsenterer, da markører ikke definerer nogen adfærd. Nyere udvikling favoriserer annoteringer for at løse nogle af de samme problemer.

3. JDK-markørgrænseflader

Java har mange indbyggede markørgrænseflader, såsom Serialiserbar, Klonabelog Fjern.

Lad os tage eksemplet med Klonabel interface. Hvis vi forsøger at klone et objekt, der ikke implementerer denne grænseflade, kaster JVM en CloneNotSupportedException. Derfor er den Klonabelmarkørinterface er en indikator for JVM som vi kan kalde Object.clone () metode.

På samme måde når du ringer til ObjectOutputStream.writeObject () metode, JVM kontrollerer, om objektet implementerer Serialiserbar markørgrænseflade. Når det ikke er tilfældet, a NotSerializableException kastes. Derfor serieliseres objektet ikke til outputstrømmen.

4. Brugerdefineret markørinterface

Lad os oprette vores egen markørgrænseflade.

For eksempel kunne vi oprette en markør, der angiver, om et objekt kan fjernes fra databasen:

offentlig grænseflade, der kan slettes {}

For at slette en enhed fra databasen skal objektet, der repræsenterer denne enhed, implementere vores Kan slettes markørgrænseflade:

public class Entity implementes Deletable {// implementeringsoplysninger}

Lad os sige, at vi har et DAO-objekt med en metode til at fjerne enheder fra databasen. Vi kan skrive vores slet () metode, således at kun objekter, der implementerer vores markørgrænseflade kan slettes:

public class ShapeDao {// andre dao-metoder public boolean delete (Object object) {if (! (object instanceof Deletable)) {return false; } // slet implementeringsoplysninger returnere true; }}

Som vi kan se, vi giver en indikation til JVM om vores objekters kørselsadfærd. Hvis objektet implementerer vores markørgrænseflade, kan det slettes fra databasen.

5. Markørgrænseflader vs. annotationer

Ved at indføre annoteringer har Java givet os et alternativ til at opnå de samme resultater som markørgrænsefladerne. Desuden kan vi, ligesom markørgrænseflader, anvende kommentarer til enhver klasse, og vi kan bruge dem som indikatorer til at udføre bestemte handlinger.

Så hvad er nøgleforskellen?

I modsætning til annoteringer tillader grænseflader os det drage fordel af polymorfisme. Som et resultat kan vi tilføj yderligere begrænsninger til markørgrænsefladen.

Lad os f.eks. Tilføje en begrænsning, som kun a Form type kan fjernes fra databasen:

offentlig grænseflade Form {dobbelt getArea (); dobbelt getCircumference (); }

I dette tilfælde, vores markørgrænseflade, lad os kalde det Sletbar form, vil se ud som følger:

offentlig grænseflade DeletableShape udvider form {}

Derefter implementerer vores klasse markørgrænsefladen:

public class Rectangle implementerer DeletableShape {// implementeringsoplysninger}

Derfor, alle Sletbar form implementeringer er også Form implementeringer. Naturligvis, vi kan ikke gøre det ved hjælp af annoteringer.

Imidlertid har hver designbeslutning afvejninger og polymorfisme kan bruges som et modargument mod markørgrænseflader. I vores eksempel udvides hver klasse Rektangel implementeres automatisk Sletbar form.

6. Markørgrænseflader vs. typiske grænseflader

I det foregående eksempel kunne vi få de samme resultater ved at ændre vores DAO'er slet () metode til at teste, om vores objekt er en Form eller ikke, i stedet for at teste, om det er en Sletelig:

public class ShapeDao {// andre dao-metoder public boolean delete (Object object) {if (! (object instanceof Shape)) {return false; } // slet implementeringsoplysninger vender tilbage sandt; }}

Så hvorfor oprette en markørgrænseflade, når vi kan opnå de samme resultater ved hjælp af en typisk grænseflade?

Lad os forestille os, ud over Form type, vil vi fjerne Person skriv også fra databasen. I dette tilfælde er der to muligheder for at opnå det:

Den første mulighed er for at tilføje en ekstra check til vores forrige slet () metode for at kontrollere, om objektet, der skal slettes, er en forekomst af Person eller ikke.

offentlig boolsk sletning (Objektobjekt) {if (! (objektinstans af figur || objektinstans af person)) {returner falsk; } // slet implementeringsoplysninger returnere true; }

Men hvad hvis vi også har flere typer, som vi også vil fjerne fra databasen? Dette vil naturligvis ikke være en god mulighed, fordi vi har det for at ændre vores metode for hver ny type.

Den anden mulighed er at lavedet Person skriv implementere Form interface, der fungerer som en markørgrænseflade. Men er en Person objekt virkelig en Form? Svaret er klart nej, og det gør den anden mulighed værre end den første.

Derfor, selvom vi kan opnå de samme resultater ved at bruge en typisk grænseflade som en markør, vi ender med et dårligt design.

7. Konklusion

I denne artikel diskuterede vi, hvad markørgrænseflader er, og hvordan de kan bruges. Så kiggede vi på nogle indbyggede Java-eksempler på denne type grænseflader, og hvordan de bruges af JDK.

Dernæst oprettede vi vores egen markørgrænseflade og afvejede den ved hjælp af en kommentar. Endelig ender vi med at se, hvorfor det er en god praksis at bruge en markørgrænseflade i nogle scenarier i stedet for en traditionel grænseflade.

Som altid kan koden findes på GitHub.