Week 19 — What are annotations in Java and how can one use them?

Question of the Week #19
What are annotations in Java and how can one use them?
6 Replies
Eric McIntyre
Eric McIntyre2y ago
Annotations are pieces of information you can put on classes, methods, locals and fields, that can specify additional information about what something does, how something should act, etc. You've probably seen them already without realizing it, @Override is an annotation that makes it easier to detect if a method is overriding a parent method. It's not required, in fact it gets removed at compile time, but it does make reading source code easier. Annotations can have values, which help the annotation describe what it's about. Things like @Contract have a value value, which is considered the "default" parameter for annotations. Naming an annotation parameter value allows this to work: @Contract("some contract"). The string "some contract" is automatically filled into value, whereas you'd have to specify the parameter name manually with other names: @Contract(value="some contract") You can also make custom annotations:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String value();
}
And here's the part where we get to limitations of annotations. Since annotations aren't technically part of the program itself (they do not get executed like everything else), they have limited functionality. You can't pass variables into annotation values, and you can only use a select few types to go along with them. You can use every primitive, String, Class, every Enum, other annotations and arrays of everything mentioned previously. Everything else won't compile. You may also have noticed that the annotation we just defined as a @Retention annotation on it, which specifies where the annotation should be. A retention of SOURCE means that the annotation will be removed once the program compiles, a retention of CLASS causes the annotation to make it into the compiled class file (but not into the runtime), which is the standard. (see next message)
Eric McIntyre
Eric McIntyre2y ago
A retention of RUNTIME causes the annotation to be present at runtime, which means that you can read the value of it out when the program is running. This is very useful for our use case, so we're using it. There is another annotation you can add to annotations, which is the @Target annotation. It takes an array of elements that describe where the annotation should be. An element type of TYPE allows the annotations to be used on class definitions, enum definitions, record definitions and other annotation definitions, FIELD allows it to be used on field declarations, METHOD on method definitions (but not constructors!), PARAMETER on method parameters, CONSTRUCTOR on class constructors, LOCAL_VARIABLE on locals, PACKAGE in package-info classes, TYPE_PARAMETER on generic type parameters, MODULE in module-info classes and RECORD_COMPONENT on record components. If your annotation is used outside of the allowed targets, the compiler will tell the user so and prevent them from using it there. When you have a retention of RUNTIME, you can get the actual annotation at runtime as well, with the values filled in by the user. Lets say our user has used MyAnnotation on a class, here's how we'd get the annotation value out:
@MyAnnotation("hello!")
class MyClass {
// something
}
class Main {
public static void main(String[] a) {
MyAnnotation annotationInstance = MyClass.class.getAnnotation(MyAnnotation.class);
System.out.println(annotationInstance.value()); // hello! as seen on MyClass
}
}
@MyAnnotation("hello!")
class MyClass {
// something
}
class Main {
public static void main(String[] a) {
MyAnnotation annotationInstance = MyClass.class.getAnnotation(MyAnnotation.class);
System.out.println(annotationInstance.value()); // hello! as seen on MyClass
}
}
Annotations are also often used in spring, where they find their use with describing how a HTTP route should act, for example. Frameworks like lombok also use source level annotations to transpile certain pieces of your code, to eliminate boilerplate. Annotations are very useful, but sadly a bit limited for their work, which I hope I will see change at some point.
⭐ Submission from 0x150#9699
Eric McIntyre
Eric McIntyre2y ago
The annotations are for creating metadate annotations added in java 5 and we use this things for example compiler help and we add annotations above the method and class example:
@Example
public class TestClass {

@example1
public void exampleMethod() {}

}
@Example
public class TestClass {

@example1
public void exampleMethod() {}

}
i know 3 famous annotations in java witch are Deprecated, Override, SuppressWarnings when you use Deprecated means we should not use this fields example:
@Deprecated
public void TestClass {

public Integer field; // when we use this compiler gives us warn

}
@Deprecated
public void TestClass {

public Integer field; // when we use this compiler gives us warn

}
We using Override for override an method actally in usual case we dont need use Override but imagine someone changed the method name in superclass and that method was overrided its known as new method in subclass But when we use Override it prevents such problems with the help of the compiler example:
interface SupuerClass {
public void superMethod();

class SubClass implements SuperClass {

@Override
public void superMethod() {
// do something
}

}

}
interface SupuerClass {
public void superMethod();

class SubClass implements SuperClass {

@Override
public void superMethod() {
// do something
}

}

}
SupressWarnings is for ignore warns for example we use an deprecated method and gives us warn but when you use SupressWarnings annotations we ignore this warns how to create my annotations? :
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) // at runtime can used in reflection
@Target(ElementType.METHOD) // you can just use this annotation on methods
@Interface MyAnnotation {

String parameter1() default "parameter1"; // default
String parameter2();

}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) // at runtime can used in reflection
@Target(ElementType.METHOD) // you can just use this annotation on methods
@Interface MyAnnotation {

String parameter1() default "parameter1"; // default
String parameter2();

}
Submission from shelon_#4695
Eric McIntyre
Eric McIntyre2y ago
Annotation are a way to add metadata to Java code. Annotations can be added in Java source files using the character @ followed by the name of the annotation. An example of an annotation is @Override which checks that a method actually overrides a method from a parent class. If it doesn't, a compile-time error is raised.
public class A{
public void a(){}
}
public class B extends A{
@Override//the annotation java.lang.Override is added to the method a()
public void a(){}
}
public class A{
public void a(){}
}
public class B extends A{
@Override//the annotation java.lang.Override is added to the method a()
public void a(){}
}
It is possible to create custom annotations. The syntax for creating annotations is similar to interfaces but with @interface instead of interface.
public @interface SomeAnnotation{}
public @interface SomeAnnotation{}
It is possible to specify where the annotation can be used by applying the java.lang.annotation.Target annotation to the custom annotation with one or more ElementType parameter:
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Target({ElementType.METHOD, ElementType.FIELD})//this annotation can be used on methods and fields
public @interface SomeAnnotation{}
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Target({ElementType.METHOD, ElementType.FIELD})//this annotation can be used on methods and fields
public @interface SomeAnnotation{}
The above annotation can be used on methods and fields:
//@SomeAnnotation//not allowed as it cannot be used on classes
public class SomeClass{
@SomeAnnotation
private int i;
@SomeAnnotation
public void a(){};
}
//@SomeAnnotation//not allowed as it cannot be used on classes
public class SomeClass{
@SomeAnnotation
private int i;
@SomeAnnotation
public void a(){};
}
By default, annotations are present in compiled class files but are not available at runtime. This behaviour can be changed by specifying a RetentionPolicy.
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)//retention can be RUNTIME, CLASS or SOURCE
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface SomeAnnotation{}
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)//retention can be RUNTIME, CLASS or SOURCE
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface SomeAnnotation{}
The default RetentionPolicy is CLASS. If the RetentionPolicy is SOURCE, it means the annotation is present in source files but is not included in compiled class files. Annotations with a RetentionPolicy of RUNTIME can be read at runtime using reflection.
import java.lang.reflect.Method;
import java.lang.reflect.Method;
Class<SomeClass> c = SomeClass.class;
Method method = c.getMethod("a");
SomeAnnotation annotation = method.getAnnotation(SomeAnnotation.class);//this returns null if the annotation is not present or the RetentionPolicy is not RUNTIME
System.out.println(annotation);
Class<SomeClass> c = SomeClass.class;
Method method = c.getMethod("a");
SomeAnnotation annotation = method.getAnnotation(SomeAnnotation.class);//this returns null if the annotation is not present or the RetentionPolicy is not RUNTIME
System.out.println(annotation);
It is possible to add more information to annotations by defining methods in the @interface declaration. These can be made optional using the default keyword.
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface SomeAnnotation{
String value();
int somethingElse() default -1;
}
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface SomeAnnotation{
String value();
int somethingElse() default -1;
}
When annotating something with such an annotation, one can add the content in it. If only a single parameter is supplied, it will use value.
public class SomeClass{
@SomeAnnotation(value="Hello World", somethingElse=1337)
public void a(){}
@SomeAnnotation("another value")//somethingElse can be omitted because it has a default value and value= can be omitted since it is called 'value'
public void b(){}
}
public class SomeClass{
@SomeAnnotation(value="Hello World", somethingElse=1337)
public void a(){}
@SomeAnnotation("another value")//somethingElse can be omitted because it has a default value and value= can be omitted since it is called 'value'
public void b(){}
}
The value of these parameters can also be read out at runtime:
Class<SomeClass> c = SomeClass.class;
Method method = c.getMethod("a");
SomeAnnotation annotation = method.getAnnotation(SomeAnnotation.class);
System.out.println(annotation.value());//Hello World
System.out.println(annotation.somethingElse());//1337
Class<SomeClass> c = SomeClass.class;
Method method = c.getMethod("a");
SomeAnnotation annotation = method.getAnnotation(SomeAnnotation.class);
System.out.println(annotation.value());//Hello World
System.out.println(annotation.somethingElse());//1337
It is only possible to use a small amount of types in annotation parameters. These include primitive types, Strings, enums, other annotations and arrays of these. In order to use something for an annotation, it needs to be constant and possible to be evaluated at compile-time (something javac could inline). It is not possible to use the result of a method call as an argument for an annotation. Annotation arguments cannot be null.
Eric McIntyre
Eric McIntyre2y ago
Another use-case of annotations is annotation processing. It is possible to intercept the Java compiler by writing an annotation processor and registering it as a service. Annotation processors can specify which annotations trigger them and when compiling classes with these annotation, the Java compiler should call the annotation processor with information about the compilation process and the classes with the said annotation. Annotation processors are able to create new classes and resources but cannot (using public or safe APIs) modify existing classes.
⭐ Submission from dan1st#7327
Eric McIntyre
Eric McIntyre2y ago
Annotations can be seen as a way to mark (annotate) your code with metadata. It is typically used by a 3rd party application in order to provide information about your code to that application. Annotations were introduced in Java 5. They are actually defined as a class in java.lang.annotation.Annotation. You can create your own annotations by creating an interface with the @ symbol before the keyword interface. An example of an annotation definition is:
@Target(ElementType.TYPE) // specifies where you allow your annotation to be used. TYPE means this annotation can be used at class level
@Retention(RetentionPolicy.RUNTIME) // specifies when the annotation can be seen. If RUNTIME is not specified, other code would not be able to read the annotation at runtime
public @interface MyAnnotation {

/**
* represents a property of the annotation
* you can specify multiple proprties
* if a property is named value(), then it would not be necessary to specify "value = x" when using the annotation,
* one can simply leave out the property name when using the annotation, which makes for easier code reading
*/
String name() default "John Doe";
}
@Target(ElementType.TYPE) // specifies where you allow your annotation to be used. TYPE means this annotation can be used at class level
@Retention(RetentionPolicy.RUNTIME) // specifies when the annotation can be seen. If RUNTIME is not specified, other code would not be able to read the annotation at runtime
public @interface MyAnnotation {

/**
* represents a property of the annotation
* you can specify multiple proprties
* if a property is named value(), then it would not be necessary to specify "value = x" when using the annotation,
* one can simply leave out the property name when using the annotation, which makes for easier code reading
*/
String name() default "John Doe";
}
In order to use annotations, you simply specify it above a java member. An example of using the above annotation in code:
@MyAnnotation //Since no 'name' property is specified, it will default to "John Doe", as defined in the annotation
public class MyClass {
}

@MyAnnotation(name = "James Gosling")
public class MyOtherClass {
}
@MyAnnotation //Since no 'name' property is specified, it will default to "John Doe", as defined in the annotation
public class MyClass {
}

@MyAnnotation(name = "James Gosling")
public class MyOtherClass {
}
Annotations can be read by other pieces of code by using reflection. Generally, devs who create frameworks write the most annotations. Some very common annotation used by most java devs are Override and SuppressWarnings() annotations, which are annotations used the compiler. Since the only property in SuppressWarnings is named value(), we can use the annotation without specifying value. One can simply say
@SuppressWarnings("all")
@SuppressWarnings("all")
Submission from Luqmaan#0205
Want results from more Discord servers?
Add your server