×

Type Annotations in Java

Only declarations were eligible for annotations in earlier versions of Java. With Java 8, you may now annotate any type use, including types in declarations, generics, and casts:

@Encrypted String data;
List<@NonNull String> strings;
my_graph = (@Immutable Graph) tmpgraph;

Type annotations aren't the most attractive feature of the new Java release, at least not at first glance. Annotations are simply syntax, after all! Tools provide the semantics of annotations (i.e., their meaning and behavior). The new type annotation syntax and useful tools are introduced in this article to increase productivity and create software of higher quality.

Time to market is more crucial than ever in the financial sector because to the shifting regulatory and market conditions. However, giving up security or quality is not an option; even a simple misunderstanding of percentages and basis points might have negative effects. Every other industry is experiencing the same situation.

Annotations are undoubtedly already being used by Java programmers to raise the calibre of their code. In Java 1.5, the @Override annotation was first introduced. It might be challenging to keep track of which implementation of a method will be used at runtime in large projects with complex inheritance trees. Modifying a method declaration could, if done carelessly, prevent a subclass method from being invoked. By doing away with a method call in this way, a flaw or security hole may be created. Developers were able to describe methods as overriding a superclass method as a result of the introduction of the @Override annotation. If the application doesn't follow the developer's goals, the Java compiler will use the annotations to alert them.

Through methods like metaprogramming, annotations have also been crucial in increasing developer productivity. Annotations are supposed to be able to instruct tools on how to write new code, modify existing code, or act when the tool is running. For instance, utilising annotations on declarations like @Entity, the Java Persistence API (JPA), which was included in Java 1.5, enables developers to declaratively express the relationship between Java objects and database entities. These annotations enable run-time generation of SQL queries and mapping files by tools like Hibernate.

Annotations are used to support the DRY (Don't Repeat Yourself) principle in the context of JPA and Hibernate. Annotations are surprisingly easy to discover whenever you go for tools to assist development best practises! Examples include using Dependency Injection to lessen coupling and Aspect Oriented Programming to separate concerns.

Type Annotation SYNTAX:

This is the basic syntax,

@Encrypted String data;
List<@NonNull String> strings;
my_graph = (@Immutable Graph) tmpgraph;

It is as simple as defining an annotation with the ElementType to add a new type of annotation. Either the ElementType.TYPE USE target, the TYPE PARAMETER target, or both targets

@Target ({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
public @interface Encrypted {      }

The target ElementType.TYPE PARAMETER indicates that the annotation can be added to a type variable's declaration, such as class MyClassT>.... Any use of a type may be the subject of an annotation, according to the ElementType.TYPE USE target (e.g., types appearing in declarations, generics, and casts).

Similar to annotations on declarations, once types are annotated in the source code, they can be both maintained in the class file and made accessible at run-time by reflection (using the RetentionPolicy.CLASS or RetentionPolicy.RUNTIME policy on the annotation definition). Type annotations differ from their predecessors primarily in two ways. First off, type annotations on the kinds of local variable declarations can also be stored in class files, unlike declaration annotations. Additionally, the complete generic type is kept and is available at runtime.

Annotations can be stored in the class file, but they have no impact on how the programme normally runs. A programmer might, for instance, specify two File variables and a Connection variable in the method's body:

File my_file = ………;
@Encrypted File encryptedFile = ………;
@Open Connection connection = …………;

If one of these files is passed to the connection's send(...) method during programme execution, the same method implementation will be called:

connection.send(my_file);
connection.send(encryptedFile);

Although the types of parameters can be annotated, methods cannot be overloaded depending on the annotated types, as would be expected given the lack of runtime effect:

public class Connection {
void send (@Encrypted File my_file) {  ……….  }
}

The reason behind this restriction is that the compiler has no way of determining the relationship between types that have various annotations or between types that are annotated and unannotated.

The connection variable is referred to as the method's "receiver" in the call connection.send(...). (The name "receiver" originates from the traditional analogy of passing messages between objects in object-oriented programming.) In order to allow type annotations to be added on a method's recipient, Java 8 changes the syntax for method declarations:

void send (@open Connection this, @Encrypted File my_file)

Once more, a method declared with the new receiver parameter syntax behaves the same as one declared with the conventional syntax because annotations have no effect on how the method is executed. In actuality, the sole purpose for which the new syntax is being used is to allow a type annotation to be written on the type of the receiver.

THE CHECKER FRAMEWORK:

A framework for checking Java annotations is the Checker Framework. Prof. Michael Ernst, co-lead of the JSR 308 specification, is the project's active open-source project manager. The framework was first released in 2007. A wide variety of annotations and checkers for identifying flaws including null-pointer dereferences, unit of measure inconsistencies, security vulnerabilities, and threading/concurrency issues are pre-packaged with the Checker Framework. The checks' outputs are reliable because they use type-checking internally; a tool utilising only heuristics might overlook potential errors, whereas a checker won't. During compilation, the framework performs these tests using the compiler API. You can also quickly build your own annotation checkers as a framework to find application-specific flaws.

The framework's objective is to find flaws without making you write a lot of annotations. Smart defaults and control-flow sensitivity are the two main aspects that enable it to achieve this. For instance, the checker believes that parameters are non-null by default for identifying null pointer issues. Conditionals can also be used by the checker to verify whether it is safe to dereference an expression.

void nullSafe (Object nonNullByDefault, @Nullable Object mightBeNull)
{
nonNullByDefault. hashCode (); //Due to default OK!
mightBeNull. hashCode ();
//This is a Warning!
if (mightBeNull != null)
{
mightBeNull. hashCode(); //Due to check OK!
}
}

In reality, you hardly ever need to insert annotations in the body of methods because the checker can infer and verify the annotations automatically thanks to defaults and control-flow sensitivity. The Java team has made sure that third party tool designers and users can make their own design decisions by keeping the semantics for annotations out of the official Java compiler. As a result, error checking can be tailored to a project's specific requirements.

You could say that having the option to define your own annotations also permits domain-specific type-checking. For instance, interest rates are frequently expressed in percentages in the banking industry, although the difference between rates is frequently expressed in basis points (1/100th of 1%). To make sure you don't confuse the two, you may define two annotations, @Percent and @BasisPoints, using the Units Checker of the Checker Framework:

BigDecimal perct = returnsPct (……);
// This statement annotates for returning @Percent
requiresBps(perct);
//Displays an error which is “@Basispoints is required”.

Because the Checker Framework is attentive to control-flow in this case, it determines that pct is a @Percent BigDecimal when the call to requiresBps(pct) is made based on two facts: A @Percent BigDecimal is tagged to be returned by returnsPct(...), and pct hasn't been reallocated before the call to requiresBps (...). To try to avoid these kinds of flaws, developers frequently utilise naming conventions. You are given a guarantee that these flaws won't exist even as the code develops and evolves thanks to the Checker Framework.

Millions of lines of code have already been run through the Checker Framework, finding hundreds of flaws in even thoroughly tested software. My favourite illustration was when the framework was used to analyse the well-known Google Collections library (now Google Guava), which uncovered null-pointer flaws that had escaped the notice of thorough testing and heuristic-based static analysis tools.

It is possible to achieve these outcomes without overcrowding the code. In reality, the Checker Framework only needs 2-3 annotations per 1000 lines of code to test a property!   


Related Topics

How to check Date is Greater in Java?

In this article, you will be acknowledged about how to check if the given date is greater than the other date or not. We are simply comparing the dates and...

7 minutes read.

Java Default Keyword

The Default keyword in java programming language is used as access modifier.If any of the variable or the constructor or the methods or the classes are not assigned with the...

3 minutes read.

Best Practices to use String Class in Java

Use String Builder or String Buffer for String concatenation in place of + operator.Compare two strings by equals( ) method instead == operator.Call .equals( ) method on a known String...

3 minutes read.

BigDecimal toString() in Java

BigDecimal is a Java class that is a part of the java.math package and the java.base module. It implements the ComparableBigDecimal> interface and extends the Number class. The BigDecimal class...

3 minutes read.

Various operations on HashSet in Java

In this article, you will be acknowledged about what is a HashSet in java and what are its operations in java programming language. The HashSet is a crucial part of...

3 minutes read.

InputMismatchException in Java

What is InputMismatchException? One of the most frequent errors in Java is the InputMismatchException. Because the InputMismatchException is a subtype of the java.lang, it is an unchecked exception. RuntimeException.Because it is...

4 minutes read.

Java 9 Interface Private Method

Java 9 provides us the facility to include private methods inside the java interface. In java 8 and earlier versions, we are supposed to use only constant variables and abstract...

3 minutes read.

Copy data/content from one file to another in java

In this article, you will be acknowledged about how to copy data or content from one file to another file. Also, you will be acknowledged about the classes and methods...

3 minutes read.

Types of JDBC Drivers

JDBC Drivers: A piece of software known as JDBC Driver permits database communication between Java applications and the server. In order to communicate with our database server, JDBC drivers put into practice...

4 minutes read.

Palindrome Partitioning problem in Java

In this article, you will be acknowledged about partitioning of the palindrome. It can be done in many ways. This article makes sure every method is discussed. Palindrome If a string remains...

6 minutes read.

RMI program in Java

Remote Method Invocation is what it stands for. An object can call the method of another object in a different space address using the RMI API, which may be on the...

3 minutes read.

Bounded buffer problem in Java

The Bounded buffer Problem can also be called a Producer consumer problem. The problem covers two processes—the producer and the consumer—that share a single, fixed-size buffer that serves as a...

4 minutes read.

Java extend multiple classes

In Java, what does extend mean? One of several Java inheritance keywords is extended, meaning we pass all or most of the Parent class's characteristics through to the Child class. The...

3 minutes read.

Java time local date

Java: Java is one of the programming language which is object oriented. It consists of many features such as robust, simple, architecture neutral, dynamic, distributed, multi threaded, portable etc. The main feature...

3 minutes read.

Java vs Go

Java: Java is an object oriented programming language. It is also known as multi threaded language. It was designed by James gosling in the year 1995. We can also say that...

4 minutes read.

Why are generics used in Java

Java has a feature called generics that allows you to make a class, interface, and function accepting any (reference) type as a parameter. In other words, it is the idea...

4 minutes read.

Alice and Bob Problem Java

Alice and Bob were two friends who liked to play games. Both together found a game, which has the description below. The game begins with an integer num, used to create...

2 minutes read.

AbstractSet Class in Java

The AbstractSet class is used for the implementation of the Abstract Collection class and interface. It is the part of Collection Frameworks. In the AbstractSet, the implementation is same as the...

3 minutes read.

Java Math cos() Method

The cos() method of Math class returns the trigonometric cosine of the specified angle. Syntax: public static double cos(double a) Parameters: The parameter ‘a’ represents an angle measured in radians. Return Value: The cos() method returns...

1 minute read.

How Many Ways to Create an Object in Java?

As you know, a class is a blueprint for an object, and you can create objects from it. There are several ways to create objects of classes in Java. This...

6 minutes read.