Java Enums and Annotations
This chapter covers two important concepts in Java for defining types and metadata: Enumerations and Annotations.
Enum
An enum is a special Java class that allows us to give meaningful names to a fixed set of constants. Using enums enhances code readability, type safety, and maintainability.
- Use the
enumkeyword to define an enumeration type. - Enum constant members are internally
public static final, and they are instances of that enum type.
Defining and Using Enums
// Define an enum representing days of the week
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
public class EnumExample {
public static void main(String[] args) {
// Assign enum constant to a variable
Day today = Day.WEDNESDAY;
// Use enum in switch statement
switch (today) {
case MONDAY:
System.out.println("Start of a new week!");
break;
case FRIDAY:
System.out.println("Weekend is coming!");
break;
default:
System.out.println("Just a regular day.");
break;
}
// Iterate over all enum constants
System.out.println("\nAll days:");
for (Day day : Day.values()) {
System.out.println(day);
}
// Get enum constant name and ordinal
System.out.println("\nToday is: " + today.name());
System.out.println("Ordinal is: " + today.ordinal()); // Ordinal starts from 0
}
}Enums with Properties and Methods
Enums are far more powerful than just a set of constants. They can have their own attributes, constructors, and methods.
- Enum constructors must be
privateor package-private. - When defining constants, parameters can be passed to the constructor using parentheses.
public enum Planet {
// Define constants and associate attributes
MERCURY(3.303e+23, 2.4397e6),
VENUS(4.869e+24, 6.0518e6),
EARTH(5.976e+24, 6.37814e6),
MARS(6.421e+23, 3.3972e6);
// Enum attributes
private final double mass; // Mass (kg)
private final double radius; // Radius (m)
// Enum constructor (implicitly private)
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
// Enum method
public double surfaceGravity() {
final double G = 6.67300E-11;
return G * mass / (radius * radius);
}
}
// Usage
// double earthGravity = Planet.EARTH.surfaceGravity();
// System.out.printf("Earth surface gravity: %f m/s^2%n", earthGravity);Annotation
Annotations are a form of metadata added to Java code. They don't directly affect code execution themselves, but can be read and processed by the compiler, tools, or runtime libraries to achieve specific functionality.
Uses of Annotations
- Provide information to the compiler: For example,
@Overridetells the compiler that a method is overriding a parent class method, and the compiler will report an error if it's not. - Compile-time processing: Software tools can process annotation information to generate code, XML files, etc.
- Runtime processing: Some annotations can be read at runtime through reflection, thus affecting program behavior.
Built-in Annotations
Java provides some standard built-in annotations:
@Override: Checks that the method is overriding a method from a parent class or interface.@Deprecated: Marks an element (class, method, etc.) as obsolete and not recommended for use. The compiler will issue a warning.@SuppressWarnings: Tells the compiler to ignore specified warning messages.@FunctionalInterface(Java 8+): Marks an interface as a functional interface (having only one abstract method).
public class BuiltInAnnotations {
@Deprecated
public void oldMethod() {
System.out.println("This is a deprecated method.");
}
@SuppressWarnings("deprecation")
public void useOldMethod() {
oldMethod(); // Compiler won't warn about calling deprecated method
}
}Custom Annotations
We can also create our own annotations. Annotations are defined using the @interface keyword.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 1. Define an annotation
@Retention(RetentionPolicy.RUNTIME) // Specify retention policy: visible at runtime
@Target(ElementType.METHOD) // Specify target: methods
public @interface MyCustomAnnotation {
// Define annotation elements (similar to methods)
String description() default "No description";
int level();
}
// 2. Use the annotation
public class MyService {
@MyCustomAnnotation(description = "This is a test method", level = 5)
public void performAction() {
// ...
}
}Custom annotations are typically used in combination with Reflection to check at runtime whether a class or method has a certain annotation and execute corresponding logic based on the annotation's element values. This is widely used in many frameworks (such as Spring, JUnit).