I 2005, med ankomsten av Java 5, ble vi kjent med nye enheter kalt merknader.

Merknader er en spesiell form for syntaktisk metadata som kan deklareres i kode. De brukes til å analysere kode ved kompilering eller under kjøring. Du kan tenke på en merknad som en etikett, kode eller kompilatorhint.

Du har sikkert støtt på merknader før. For eksempel, når vi overstyrer en metode for den overordnede klassen, skriver vi @Override før selve metoden. Denne merknaden indikerer at forelderens metode vil bli overstyrt i barneklassen.

Syntaks:

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

Jeg vil med en gang merke meg at merknader ikke bare gjelder metoder. De brukes med pakker, klasser, metoder, felt og parametere.

For å forstå hvordan merknader fungerer, la oss først bli kjent med konseptet med et markørgrensesnitt. Siden bruken av Java har utviklere alltid trengt en måte å merke klasser for å utføre visse handlinger på dem.

Før Java 5 brukte de et grensesnitt som ikke gjorde det vi forventer at grensesnitt skal gjøre. Den hadde ingen metoder og ingen kontrakt. Det markerte bare en klasse som spesiell på en eller annen måte.

Et slikt grensesnitt ble kalt et markørgrensesnitt. Fra navnet kan du gjette at formålet er å merke klasser for JVM, kompilator eller et eller annet bibliotek. Noen markørgrensesnitt, som Serializable , gjenstår. Dette markørgrensesnittet lar oss indikere at forekomster av en klasse kan serialiseres.

Som vi har sett, fortsetter markørgrensesnitt å leve videre selv etter introduksjonen av merknader.

Merknader kontra markørgrensesnitt:

@MyAnnotation
public class MyClass {}
public class MyClass implements MarkerInterface {}

Begge tilnærmingene har samme mål, men det er en klar forskjell i implementeringen. Vurder for eksempel et grensesnitt og en merknad som indikerer at en klasse tilhører en bestemt type.

Hvis vi bruker et grensesnitt, merker vi klassen. Hvis vi bruker det feil og det oppstår en feil, vil vi oppdage problemet ved kompilering og programmet vil ikke kjøre.

Med merknader er ikke alt så enkelt: her vil feilen bli oppdaget ved kjøretid, noe som betyr at programmet starter, men ikke overraskende vil det ikke fullføres.

Merk at hvis vi trenger å merke en klasse for fremtidig bruk, må dens forekomster sendes 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
}

Et markørgrensesnitt fungerer best her.

Det er best å bruke merknader når vi trenger noe mer, for eksempel parameterne som merknader støtter.

La oss se på standardkommentarene i JDK:

Merknad Beskrivelse Eksempel
@Overstyring Spesifiserer at en metode overstyrer en superklasses metode eller implementerer en metode for en abstrakt klasse eller grensesnitt.
@Override
public int hashCode() {
        return super.hashCode();
}
@Utviklet Merker koden som utdatert.
@Deprecated
public abstract void method();
@SuppressWarnings Deaktiverer kompilatoradvarsler for det kommenterte elementet. Merk at hvis du trenger å deaktivere flere kategorier av advarsler, må de være omsluttet av krøllete klammeparenteser, for eksempel @SuppressWarnings({"unchecked", "cast"}) .
public class DocumentsFolder {
   private List documents;

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

I dette eksemplet prøver vi å legge til en liste som ikke har en definert type (en generisk type). Kompilatoren vil advare oss om dette. Dette er veldig nyttig, men noen ganger er det for mange "advarsler" og de kan være støyende. Du kan bruke denne metodekommentaren og spesifisere en type kompilatoradvarsel som et argument. Det er mange markører, så ikke bekymre deg for å huske dem alle - IDEA vil vanligvis fortelle deg hvilken du skal legge til.

Et annet eksempel med flere argumenter:

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