I 2005, med ankomsten af ​​Java 5, lærte vi nye entiteter at kende kaldet annoteringer.

Annoteringer er en særlig form for syntaktisk metadata, der kan erklæres i kode. De bruges til at analysere kode ved kompilering eller ved kørsel. Du kan tænke på en annotering som en etiket, tag eller compilertip.

Du har sikkert stødt på anmærkninger før. For eksempel, når vi tilsidesætter en metode fra den overordnede klasse, skriver vi @Override før selve metoden. Denne annotation angiver, at forældrenes metode vil blive tilsidesat i børneklassen.

Syntaks:


@Override
public int hashCode() {
      return super.hashCode();
}

Jeg vil med det samme bemærke, at annoteringer ikke kun gælder for metoder. De bruges med pakker, klasser, metoder, felter og parametre.

For at forstå, hvordan annoteringer fungerer, lad os først stifte bekendtskab med konceptet med en markørgrænseflade. Siden fremkomsten af ​​Java har udviklere altid haft brug for en måde at markere klasser på for at udføre visse handlinger på dem.

Før Java 5 brugte de en grænseflade, der ikke gjorde, hvad vi forventer, at grænseflader gør. Det havde ingen metoder og ingen kontrakt. Det markerede bare en klasse som speciel på en eller anden måde.

En sådan grænseflade blev kaldt en markørgrænseflade. Ud fra navnet kan du måske gætte, at dets formål er at markere klasser til JVM, compiler eller et eller andet bibliotek. Nogle markørgrænseflader, såsom Serializable , forbliver. Denne markørgrænseflade lader os indikere, at forekomster af en klasse kan serialiseres.

Som vi har set, fortsætter markørgrænseflader med at leve videre, selv efter introduktionen af ​​annoteringer.

Annoteringer kontra markørgrænseflader:


@MyAnnotation
public class MyClass {}

public class MyClass implements MarkerInterface {}

Begge tilgange har samme mål, men der er en klar forskel i deres implementering. Overvej for eksempel en grænseflade og en anmærkning, der angiver, at en klasse tilhører en bestemt type.

Hvis vi bruger en grænseflade, så markerer vi klassen. Hvis vi bruger det forkert, og der opstår en fejl, opdager vi problemet ved kompileringen, og programmet kører ikke.

Med annoteringer er alt ikke så enkelt: her vil fejlen blive opdaget under kørsel, hvilket betyder, at programmet starter, men ikke overraskende slutter det ikke.

Bemærk, at hvis vi skal markere en klasse til fremtidig brug, skal dens forekomster videregives til en bestemt metode:


public class MyInteger implements Sum {}
interface Sum {};

public static void main(String[] args) throws IOException {
        increase(new MyInteger());
}
 
public static void increase(Sum count) {
        // TODO
}

En markørgrænseflade fungerer bedst her.

Det er bedst at bruge annoteringer, når vi har brug for noget mere, såsom de parametre, som annoteringer understøtter.

Lad os se på standardannoteringerne i JDK:

Anmærkning Beskrivelse Eksempel
@Tilsidesæt Specificerer, at en metode tilsidesætter en superklasses metode eller implementerer en metode for en abstrakt klasse eller grænseflade.

@Override
public int hashCode() {
        return super.hashCode();
}
@Forældet Markerer koden som forældet.

@Deprecated
public abstract void method();
@SuppressWarnings Deaktiverer compileradvarsler for det kommenterede element. Bemærk, at hvis du har brug for at deaktivere flere kategorier af advarsler, skal de være omgivet af krøllede klammeparenteser, for eksempel @SuppressWarnings({"unchecked", "cast"}) .

public class DocumentsFolder {
   private List documents;

   @SuppressWarnings("unchecked")
public void addDocument(String document) {
            documents.add(document);
   }
}

I dette eksempel forsøger vi at tilføje til en liste, der ikke har en defineret type (en generisk type). Oversætteren vil advare os om dette. Dette er meget nyttigt, men nogle gange er der for mange "advarsler", og de kan være støjende. Du kan bruge denne metodeanmærkning og angive en type compileradvarsel som et argument. Der er mange markører, så du skal ikke bekymre dig om at huske dem alle - IDEA vil normalt fortælle dig, hvilken du skal tilføje.

Et andet eksempel med flere argumenter:


@SuppressWarnings({"unchecked", "deprecated"})