How To Use Annotations In Java Language?

Annotations In Java

As a Computer Science Student, if you have completed learning the Basics Java Language Course and are eyeing towards the Advanced Java Concepts where you must deal with the Java Frameworks and Libraries, understanding “Annotations in Java” becomes important.

Annotation is a special concept in Java that provides additional information about the code to the compiler without harming program execution. We can say that Java Annotation is the bridge between the Core Java Concepts and the Advanced Java Concepts like Frameworks.

If you’re new to Java, you may want to learn the fundamentals of Java programming before diving into advanced concepts like annotations.

In this article, we are going to define the Java Annotation first. Then, we will discuss different types of Annotations in Java and practically implement them. So, let us start our journey.

Whether you’re a beginner or looking to refine your Java skills, getting expert guidance can be invaluable.

Summary Or Key Highlights: 

  • Annotation is used to provide Metadata about the code to the compiler for better program execution.
  • Annotation is denoted with the ‘@’ Symbol in the Java Programming Language.
  • We can divide Java Annotations into 4 Categories based on their Structure.
  • We can divide Java Annotations into mainly 2 Categories based on their Origin.
  • Java Annotations play a direct role in different Java Frameworks and Libraries.

What Are Annotations In Java Language? Read Below

Java Annotations are the special Notes or Labels that we can write in our Java Codes to provide more information to the Java Compiler. We can assume this like a “Sticky Note” in the Java program that informs the Compiler to perform a certain task without harming the program execution.

General Syntax: @AnnotationName

In Java, whatever we write after the ‘@’ Symbol will be considered the Annotation. So, the ‘@’ Symbol is preserved for the Annotation purposes only. We can use the Annotations to increase the Functionality and Readability of the code along with creating interaction with frameworks.

Historical Evolution Of Java Annotations:

  • 1990s: No Annotation Support present at this time. Developers need to rely on the XML for Metadata.
  • 2000s: The java.lang.annotation was introduced and with it all other Annotations became available.
  • 2010s: The Type Annotations were introduced and the usage of the annotations was expanded.
  • 2020s: Annotations are improving to provide support to Modular Applications.

What Are Different Types Of Annotation Based On Origin?

Now, after discussing Different Types of Annotation based on their Structure, we can move ahead to the section where we will discuss different types of Java Annotations based on their Origin.

Based on the origin, the Java Annotations can be divided into mainly 2 Categories, Built-In and Custom Annotation. Let us first start with the Built-In Java Annotations.

Different Types Of Java Annotations Based On Origin

1. Built-in Annotations In Java:

The Built-in Java Annotation can further be divided into 2 Categories. One is the General-purpose Annotation that interacts with the Compiler and provides information hints. Another one is the Meta Annotation which helps to define other annotations in Java.

Let us check the following list to know more about the General-purpose Annotations and Meta Annotations.

[> General-purpose Annotation: 

  • @Override: This annotation helps to override any Superclass or Parent Method by the Child Method.
  • @Deprecated: This annotation is used to mark any methods as Outdated in the program.
  • @SuppressWarnings: This annotation instructs the compiler to Suppress Certain Warnings.

 [> Meta Annotations:

  • @Retention: This annotation is used to check whether the annotation is present in Runtime or not.
  • @Documented: If we use this annotation, in generated Java Documents we will get an annotation.
  • @Target: This annotation helps to target any element like Method, or Class to create an annotation.
  • @Inherited: If we use this annotation, the annotation will be inherited by the Child Classes.
  • @Repeatable: If we use this annotation, we can use its multiple instances with the same annotation.

2. Custom Annotations: 

Other than the Built-in Annotations, in Java, we can define Custom Annotations as well. For the Custom Annotations, we will use the @Interface to provide a name to the Custom Annotation. 

Also, in Custom Annotation, we have to use the @Retention annotation as well. In Custom Java Annotations, we have to use the java.lang.reflect.Method which is part of the Java Reflection API.

To further explore Java’s capabilities, you might find Optional Parameters in Java useful, as it explains how to work with optional arguments in methods.

What Are Different Types Of Java Annotations Based On Structure?

Now, we hope the Definition of the Java Annotations has become clear to you. So, we can move ahead for the Different Types of Java Annotations. In this section, we will discuss Different Types of Java Annotations based on their Structure and Syntax.

Each Java Annotation has a different Syntax to write. Based on that, we can divide the Java Annotations into 4 Categories. Let us have a look at the following list to know more about it.

Different Types Of Java Annotations Based On Structure

  • Marker Annotation: If any Annotation is written without any Elements or Values, then that Annotation will be called the Marker Annotation. The Marker Annotation helps to Tag or Identify the Code Behaviors. Some Marker Annotations are @Override, @Deprecated, etc. 
  • Single-Value Annotation: If any Annotation can only accept only 1 Element or Value, then that annotation will be called a Single-Value Annotation. With this, we can do an Assignment of Values. An example of Single-Value Annotation is @SuppressWarnings.
  • Multi-Value Annotation: If any Annotation can contain Multiple Elements or Values, then this will be called a Multi-Value Annotation. This helps in Annotation-based Configurations. @Target can be an example of Multi-Value Annotation.
  • Type Annotation: This annotation is completely different. For finding out the Type of any element, this annotation is used. Annotation usage is very rare. The @Documented can be an example.

Quick Recap of Java Annotations:

  • Java Annotations are Special notes to provide instructions tothe  Java Compiler about a specific task.
  • The Java Annotations were first introduced in the 2000s with the java.lang.annotation Package.
  • @Override and @Deprecated are General Purpose, and @Retention and @Target are Meta Annotations both of which are a part of the Built-In Annotation.
  • Other than the Built-in Annotation, the Java Annotations can be divided into Custom Annotation Categories based on Origin.
  • Where No Elements are present in the Annotation, that is the Marker Annotation.
  • If Single Element is present, then Single-Value and for Multiple Element, it is the Multi-Value Annotation.
  • If the Annotation works with any Target Element, it will be the Target Annotation in Java.

How To Implement Different Types Of Annotation In Java?

We hope that whatever we have discussed till now, will be enough to clear your understanding of the Java Annotations. Now, it is time to move ahead for Practical Implementation. 

In this section, we will show how to practically implement Java Annotations. Let us check the following examples to learn more about the development process.

Example 1: Override Annotation 

We will start with the Override Annotation. The Override Annotation can only be used if any Inheritance exists in the Java Program. The Override Annotation helps to override the Parent Class by the Child Class.

				
					class ZapOne { // This Is The Parent Class
    void show() {
        System.out.println("ZapOne Class");
    }
}

class CodingZap extends ZapOne { // This Is The Child Class
    @Override // @Override Annotation
    void show() {
        System.out.println("CodingZap Class Override");
    }
}

public class Main {
    public static void main(String[] args) {
        CodingZap sg = new CodingZap();
        sg.show(); // Calling The Child Function
    }
}


				
			

Steps Of The Program: 

  • At first, the Parent Class “ZapOne” will be implemented with the Show() Function.
  • Later, the Child Class “CodingZap” will be extended to the Parent Class which will also have the Show() Function.
  • In the Child Class, the @Override Annotation will be written to override the Parent Class.
  • Now, in the Main Function, we will create the Child Class Object and call the Show() Function.
  • This will provide the Statement written under the Child Class as Parent Class is Overridden.

Output: 

Output Override Annotation

Example 2: Deprecated Annotation

In any Java Program, if we are using any Class or Method that is outdated, then the Deprecated Annotation will be used. This helps to advertise not to use that Method or Class for execution

				
					class ZapOne {
    @Deprecated // This Method Will Be Deprecated
    void old() {
        System.out.println("ZapOne Is A Deprecated Method");
    }
    
    void newm() {
        System.out.println("A New Method Inside Deprecated");
    }
}

public class Main {
    public static void main(String[] args) {
        ZapOne sg = new ZapOne();
        // Calling The Deprecated Methods
        sg.old();
        sg.newm();
    }
}


				
			

Steps Of The Program: 

  • At first, a Class “ZapOne” will be implemented where we will mention the @Deprecated Annotation.
  • Inside that, we will implement a function Old() which will become outdated due to the annotation.
  • Below the Old() Function, a New Function Newm() will be created.
  • Now, in the Main Function, we will create the Object of the “ZapOne” Class.
  • Using the object, we will access the Outdated and New Functions both. 
  • So, in the output, both the function will print the statements. If we don’t manually access the Old() Function, it will not show in the output.

Output: 

Deprecated Annotation

Example 3: SuppressWarnings Annotation

As a developer, if we anticipate any Compiler warnings on our program, we can suppress that with the help of the SuppressWarnings Annotation. This helps to get a clear output without having any warnings.

				
					import java.util.ArrayList;

public class Main {
    @SuppressWarnings(“Unchecked”) // We Will Get Suppress Warnings For Unchecked Operations
    
    public static void main(String[] args) {
        ArrayList sg = new ArrayList(); // A Raw Type Of ArrayList Will Be Created
        
        sg.add(“CodingZap”); // Adding The Value
        System.out.println(“List Element Is: “ + sg.get(0));
    }
}


				
			

Steps Of The Program: 

  • In the Main Function, we will mention the @SuppressWarnings Annotation only for Unchecked Operations.
  • So, if the Compiler tries to provide any Unchecked Operation Warnings, it will be restricted.
  • Now, we will make a Raw ArrayList in the Main Function. Then, we will add the String Value “CodingZap”.
  • In the end, we will try to print the value. In this case, the compiler should give the warning. However, due to annotation, it will not provide any warning.

Output: 

SuppressWarnings Annotation Output

Example 4: Retention Annotation

Now, it is time to implement the Retention Annotation. Retention is used to specify the life cycle of any annotation. If the Retention is used for the RUNTIME, the annotation will be available only for Runtime.

				
					import java.lang.annotation.*;
import java.lang.reflect.Method;

// We Will Define An Annotation That Is Retained At Runtime
@Retention(RetentionPolicy.RUNTIME)
@interface ZapRetention {
    String value();
}

public class Main {
    @ZapRetention("This Is A Retention Annotation")
    public void zap() {}

    public static void main(String[] args) throws NoSuchMethodException {
        // We Will Use The Zap Method Under Annotation
        Method sg = Main.class.getDeclaredMethod("zap");
        
        // We Will Retrieve Annotation From Method
        ZapRetention sg1 = sg.getAnnotation(ZapRetention.class);
        System.out.println("Annotation Value: " + sg1.value());
        
    }
}


				
			

Steps Of The Program: 

  • At first, we will use the @Retention Annotation using the Runtime Retention Policy.
  • With the help of the @Interface Annotation, we will create the @ZapRetention Annotation.
  • Now, in the Main Function, we will create an object of the Method using the declared Zap() Function.
  • Later, we will create an Annotation Object and access the Annotation Value that is given in the code.

Output: 

 Output- Retention Annotation

Example 5: Inheritance Annotation

The Inheritance Annotation is different from the Override Annotation, though it is also used on the Inheritance. In the Inheritance Annotation, the defined annotation passes through the Child Classes from the Parent Class.

				
					import java.lang.annotation.*;

// We Will Define An Annotation That Will Be Inherited
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface ZapInherited {
    String value();
}

// We Will Apply Annotation To Parent Class
@ZapInherited("Inherited Annotation In ZapOne Parent Class")
class ZapOne { // Parent Class
}

class CodingZap extends ZapOne { // Child Class
}

public class Main {
    public static void main(String[] args) {
        // We Will Retrieve Inherited Annotation From Child
        ZapInherited sg = CodingZap.class.getAnnotation(ZapInherited.class);
        
        System.out.println("Inherited Annotation Value: " + sg.value());
    }
}


				
			

Steps Of The Program: 

  • At first, we will create Multiple Annotations using the @Inherited, @Retention, @Target, and @Interface Annotations.
  • The @Inherited Annotation marks the annotation will be inherited by the Child Classes.
  • The @Retention Annotation will make the annotation available during Runtime for Reflection.
  • The @Target annotation will make sure that the annotation is applied to Classes or Interfaces.
  • Now, the Inheritance Annotation will be applied to the Parent Class “ZapOne”.
  • We will create the Child Class “CodingZap” which will also get that annotation automatically.
  • Now, in the Main Function, we will get the Inheritance Annotation from the Child Class.
  • When we print the value, we will see the Annotation Value coming on the screen.

Output: 

Output- Inheritance Annotation

Comparison Table Between Different Java Annotations:

Now, as we have discussed so many things about Java Annotations, let us wrap up by discussing a Comparison Table between them. In this section, we will make a Comparison Table on all Java Annotations based on categories like Type, Retention Policy, Usage Field, etc.

So, let us check the following Comparison Table to learn more about Java Annotations.

Annotation Names

Type

Usage Fields

Retention Policy

@Override

Marker

Methods

SOURCE

@Deprecated

Marker

Classes, Methods, Fields

CLASS

@SuppressWarnings

Single-Value

Methods, Fields, Classes

CLASS

@Retention

Meta

Other Annotations

RUNTIME

@Target

Meta

Other Annotations

RUNTIME

@Inherited

Meta

Other Annotations

RUNTIME

@Documented

Meta

Other Annotations

RUNTIME

@Repeatable

Meta

Other Annotations

RUNTIME

Custom

User-Defined

Classes, Methods, Fields

SOURCE/ CLASS/ RUNTIME

Comparison Table Between Java Annotations And Similar Concepts In Other Languages:

Now, if you are thinking that the Annotation-like concept is only present in Java Programming, then you are thinking wrong. We will also get Annotation Concepts in different Other Programming Languages. But, there the Name and Working Process are slightly different.

Let us check the following Comparison Table between Java Annotations and Similar Concepts in other Languages to clarify the concept more.

Category

Java Annotations

C# Attributes

Python Decorators

Purpose

Configuration

Reflection

Modification

Syntax

@Override

[Obsolete]

@staticmethod

Custom Annotation

@Interface

Derived from Attribute

Function-based Decorators

Reflection Support

Yes

Yes

Limited

Framework Support

Spring, Hibernate

ASP.NET, Entity

Flask, Django

What Is The Role Of Annotation In Different Java Frameworks?

We have learned that Java Annotations are crucial to working with Java Frameworks. Java annotations are even termed the gateway to learning Java frameworks. Now, it is time to prove that. In this section, we will show how different Java Frameworks are dependent on different Java Annotations. 

Let us check the following list to learn more about the relationship between Java Annotation and Frameworks.

  • The @Component, @Autowired, and @Configuration annotations are needed to do Dependency Injection & Configuration in Spring Framework.
  • To do Object-Relational Mapping in the Hibernate Framework, the @Entity, @Table, and @Id annotations are used.
  • @Controller, @RequestMapping, @WebServlet, etc. are the annotations used to do Web Development using the Spring MVC Framework.
  • If you are working with JUnit Framework, then the use of @Test, @BeforeEach, etc. annotation is important to do Testing.
  • @PreAuthorize, @Secured, etc. annotations are used to provide Security & Authorization in Jakarta EE Framework.

Real-World Example Demonstrating Annotations In The Spring Framework:

In the above section, we have seen that different Java Annotations play an important role in different Java Frameworks. Now, it is time to understand it more deeply with a simple practical approach.

Here, we will use the @Autowired Annotation to do simple Dependency Injection with Spring Framework. However, to do this, you should have a deep understanding of Spring Framework as well.

The Dependency Injection is highly used in the E-Commerce, Banking, and Healthcare Sectors. Here, the @Autowired helps to inject the Service into the Controller. Let us check how this is done with the Simple Code Snippet.

				
					// Service Class Implementation
@Service
public class Serv 
{
    public String get() 
    {
        return "CodingZap User";
    }
}

// Controller Class Implementation With RestController
@RestController
public class Control 
{
    @Autowired // @Autowired Annotation
    private Serv Data;

    // Marking The End Of The @Autowired Annotation
    @GetMapping("/user") 
    public String get() 
    {
        return Data.get();
    }
}



				
			

In this Code Snippet, a Service Class will be defined that will share the User Name. Now, the Controller Class will be defined that will inject the Data in the RestController Class. In the end, when the code hits the GetMapping, it will be marked as the end of the @Autowired Annotation.

What Are Some Security Considerations With Java Annotations?

As we have discussed so many things about Java Annotations, you should be eager to work with it. However, when you are working with the Java Annotations, you keep in mind some Security Considerations as well. Otherwise, you can face some serious challenges.

Let us check the following list to know more about the Security Considerations with Java Annotations.

  • If the annotations are not secured, the attacker might access Private Methods and Classes.
  • While doing Dynamic Annotation, we should be careful with the Injection Vulnerabilities.
  • We should not store Confidential Information in Annotations as they can be exposed during Runtime.
  • If we are using Custom Annotations, we should validate them to restrict Malicious Input Data.
  • If we use Multiple Reflections to read Annotations, it can create Security Loopholes.

What Are Some Common Errors With Java Annotations?

Now, while working with Java Annotations along with some Security Considerations, we should keep in mind some Common Errors as well. These are the Errors that every student commits when they have started learning Annotations. So, we should be careful.

Let us have a look at the following list where some Important Common Errors are mentioned.

  • Oftentimes, we provide the Wrong Spelling of any Annotation. Then, we will get the Error.
  • In most cases, we place the Annotations in any place. But, they should be placed before any Method.
  • While using Multiple Annotations, oftentimes, we place Contradictory Annotations in the same code.
  • Sometimes, we forget to Provide Parameters to the Java Annotations where it is required.
  • During the Custom Annotation development, sometimes, we forget to use the @Retention Annotation.

What Are Some Java Annotations Best Practices?

As we approach the end of the discussion, let us conclude our journey by shedding some light on the Java Annotation Best Practices. If you want to become an expert in Java Annotations and eventually in Java Frameworks, then you should follow these best practices.

Let us check the following list to know more about some important Best Practices on Java Annotation.

  • We should always try to use Built-in Annotations rather than Custom Annotations.
  • While using Custom Annotation, we should provide Meaningful Names.
  • We should use Simple Annotation Logic to make the code less complex to understand.
  • While combining Multiple Annotations, we should be careful to avoid issues.
  • We should choose the correct Retention Policy based on the Annotation Purpose.

Conclusion:

In the end, we can say that it is very important to know about the “Annotations in Java”.

The Java Annotations are going to be your Foundation for most of the Java Advanced Subjects. However, we will advise you to clear the Basics of Java Programming before starting a complex subject like Java Annotation. Then, you can feel that Java Annotation has become a breeze for you.

If you’re preparing for Java interviews, our Top Java Interview Questions and Answers can help you brush up on key concepts, including annotations.

Takeaways: 

  • Marker, Single-Value, and Multi-Value are some types of Java Annotations based on their Structure.
  • Built-in and Custom Annotations are the types of Java Annotations based on their Origin.
  • Built-in annotations can be further divided into General-Purpose and Meta Annotations.
  • Some of the Built-in Annotations are @Override, @Deprecated, @Retention, etc.
  • We can define Custom Annotations using the @Interface Annotation in Java Programming.