Replacing Enums with Enumerated AnnotationsEdit PagePage History

Overview

“Magic constants” of type annotations zijn gewone oude Java constanten versierd op een manier die tools in staat stelt om ze te herkennen als speciale waarden. Hun syntaxis is niet anders dan die van andere Java constanten. In plaats daarvan moet een annotatie met een gemakkelijk leesbare naam worden gemaakt die alle verwante constanten opsomt.

Deze annotatie kan dan een return value of een method parameter versieren, waarmee hints worden gegeven aan de gereedschappen die je gebruikt over de waarden die worden geaccepteerd of kunnen worden verwacht. Hun belangrijkste doel is om typeveiligheid af te dwingen voor methodeparameters en/of methode-retourwaarden tijdens het schrijven van de broncode.

Dit wordt typisch gebruikt om enums te vervangen. Google ontmoedigt het gebruik van enums bij de ontwikkeling van Android apps zoals vermeld in hun richtlijnen voor ontwikkelaars: “Enums vereisen vaak meer dan twee keer zoveel geheugen als statische constanten. U moet het gebruik van enums op Android ten strengste vermijden.”

IntDef

IntDef is een manier om een integer enum te vervangen wanneer er een parameter is die alleen expliciete int-waarden moet accepteren. Stel bijvoorbeeld dat we het type van een feed item willen vastleggen zoals hieronder getoond:

public class ItemTypeDescriptor { public static final int TYPE_MUSIC = 0; public static final int TYPE_PHOTO = 1; public static final int TYPE_TEXT = 2; public final int itemType; public ItemTypeDescriptor(int itemType) { this.itemType = itemType; }}

Op dit moment is er geen validatie om er zeker van te zijn dat het type dat in de constructor wordt doorgegeven geldig is. We kunnen IntDef gebruiken om ervoor te zorgen dat de waarde een van de verwachte waarden is door annotaties toe te voegen:

public class ItemTypeDescriptor { // ... type definitions // Describes when the annotation will be discarded @Retention(RetentionPolicy.SOURCE) // Enumerate valid values for this interface @IntDef({TYPE_MUSIC, TYPE_PHOTO, TYPE_TEXT}) // Create an interface for validating int types public @interface ItemTypeDef {} // Declare the constants public static final int TYPE_MUSIC = 0; public static final int TYPE_PHOTO = 1; public static final int TYPE_TEXT = 2; // Mark the argument as restricted to these enumerated types public ItemTypeDescriptor(@ItemTypeDef int itemType) { this.itemType = itemType; }}

Dezelfde constructor aanroep uit het laatste voorbeeld zal nu een fout laten zien in Android Studio omdat het nu weet welke waarden te verwachten. Raadpleeg de officiële Android annotaties gids voor meer details.

StringDef

StringDef is op dezelfde manier een manier om een string enum te vervangen waar er een parameter is die alleen expliciete string waarden moet accepteren. Stel bijvoorbeeld dat we de waarde voor een instelling willen vastleggen zoals hieronder getoond:

public class FilterColorDescriptor { public static final String FILTER_BLUE = "blue"; public static final String FILTER_RED = "red"; public static final String FILTER_GRAY = "gray"; public final String filterColor; public FilterColorDescriptor(String filterColor) { this.filterColor = filterColor; }}

Op dit moment is er geen validatie om er zeker van te zijn dat het type dat in de constructor wordt doorgegeven geldig is. We kunnen StringDef gebruiken om ervoor te zorgen dat de waarde een van de verwachte waarden is door annotaties toe te voegen:

public class FilterColorDescriptor { // ... type definitions // Describes when the annotation will be discarded @Retention(RetentionPolicy.SOURCE) // Enumerate valid values for this interface @StringDef({FILTER_BLUE, FILTER_RED, FILTER_GRAY}) // Create an interface for validating String types public @interface FilterColorDef {} // Declare the constants public static final String FILTER_BLUE = "blue"; public static final String FILTER_RED = "red"; public static final String FILTER_GRAY = "gray"; // Mark the argument as restricted to these enumerated types public FilterColorDescriptor(@FilterColorDef String filterColor) { this.filterColor = filterColor; }}

Dezelfde constructor aanroep uit het laatste voorbeeld zal nu een fout laten zien in Android Studio omdat het nu weet welke waarden te verwachten. Raadpleeg de officiële Android annotaties gids voor meer details.