How useful are annotations in Java?

When I first studied Java, when I saw about Annotations I only saw that they are useful for generating metadata, but I did not see anything that influenced the behavior of the program. Basically, I only saw Annotations to mark class authors, what the class was made for, etc...

But reading relevant Java code, I saw a lot of Annotations with uses that I don't know about, here's an example of a Hello world using Spring:

Http://projects.spring.io/spring-framework/#quick-start

From what I've been researching, if well used Annotations can even be more flexible than C/C++preprocessors!

What are the general utilities of Annotations in Java?

Author: Omni, 2014-05-29

3 answers

The most basic concept is: annotations are metadata .

Is additional data that you relate to classes, methods, attributes, parameters, and variables.

The data can be used at the time of compilation and execution, as defined by the annotation.

Preprocessing during compilation

At compile time, annotations can be used, for example, for additional code generation or even for modification in the bytecode of the class.

Compile time annotations are removed in bytecode and are not available at runtime.

Let's look at some ideas about what you can do with it.

Code generators and manipulators

For example, Hibernate can add methods wrappers to the original getters of the class to be able to load data in lazy mode. Speak Greek? This means that if you have the entities entities Cliente and Conta and call a method cliente.getConta(), it will actually call a substitute method generated by Hibernate which, in case the account has not already been read from the database, will do a SELECT and create the object conta with the respective data, then returning the loaded value.

Another example of preprocessing is the Lombok project. It is capable of generating the most common routines used in POJOs, such as getters , setters, toString () and hashCode () . Here's an example, see what the annotation @Data is capable of doing:

@Data(staticConstructor="of")
public class Company {
    private final Person founder;
    private String name;
    private List<Person> employees;
}

The above code is equivalent to the following:

public class Company {
    private final Person founder;
    private String name;
    private List<Person> employees;

    private Company(final Person founder) {
        this.founder = founder;
    }

    public static Company of(final Person founder) {
        return new Company(founder);
    }

    public Person getFounder() {
        return founder;
    }

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public List<Person> getEmployees() {
        return employees;
    }

    public void setEmployees(final List<Person> employees) {
        this.employees = employees;
    }

    @java.lang.Override
    public boolean equals(final java.lang.Object o) {
        if (o == this) return true;
        if (o == null) return false;
        if (o.getClass() != this.getClass()) return false;
        final Company other = (Company)o;
        if (this.founder == null ? other.founder != null : !this.founder.equals(other.founder)) return false;
        if (this.name == null ? other.name != null : !this.name.equals(other.name)) return false;
        if (this.employees == null ? other.employees != null : !this.employees.equals(other.employees)) return false;
        return true;
    }

    @java.lang.Override
    public int hashCode() {
        final int PRIME = 31;
        int result = 1;
        result = result * PRIME + (this.founder == null ? 0 : this.founder.hashCode());
        result = result * PRIME + (this.name == null ? 0 : this.name.hashCode());
        result = result * PRIME + (this.employees == null ? 0 : this.employees.hashCode());
        return result;
    }

    @java.lang.Override
    public java.lang.String toString() {
        return "Company(founder=" + founder + ", name=" + name + ", employees=" + employees + ")";
    }
}

Developer help

Also, annotations can be used for certain types of validation in the build. Take for example the annotation @Override. It defines that a subclass method is overwriting a superclass method. Apparently this does not help in Nothing... until someone changes the method signature in the superclass. If someone changes the method in the superclass your subclass method would become a different method. In this case, the compiler will warn you that your method with @Override is not overwriting anything else! This helps a lot to detect problems, for example, when updating a library.

The sky is the Limit

Other tools generate annotation-based configuration files to improve the runtime performance.

Anyway, you can make your own annotation processor to run in the compilation of a program and generate whatever you want, just use the API APT (Annotation Processing Tool), available from Java. See an article on the subject.

Runtime inspection

Notes that are maintained at runtime can be used by libraries and frameworks to identify the elements and perform additional annotations.

Automatic setting

In the case of Spring, for example, you must have seen that you can annotate the class as follows:

@Component
public class MessagePrinter { ... }

What's the magic here? When Spring is started through the listener in your web.xml, it will read all classes within the configured package(s) and add to the list of managed components whenever it encounters an annotation like this.

There you do not you need more of those gigantic XMLs that needed to be updated every time you changed a package class or renamed it.

For more details about Spring, Read My Article what annotations to use in Spring components 3.

Dependency Injection

Also, an annotation like @Autowired allows you to specify to Spring that attribute should be populated with some component of that type. Example:

@Autowired ClienteDAO clienteDAO;

Ready. No XML, no frills. If there is a ClienteDAO class with a spring annotation, it will automatically create an instance of it and assign it there!

Automatic formatting

Many frameworks do the magic of automatically sending and retrieving data from HTML forms, databases, files, etc. This is pretty cool, but how to specify the format of the data? Remembering that, for example, a date attribute can have different representations in the same dataset.

For example, in the JPA you can specify whether the field with a Date should save only the date or time as well:

@Temporal(TemporalType.DATE)
@Column(name="CAMPO_DATA")
public Date getData()

Without this, you would have to write code or configuration to a file.

In Spring, you can use the annotation @DateTimeFormat to define the date format when it is converted to and from a String. So Spring can automatically receive the submitted data from a form HTML and convert them properly to the types of a class.

To infinity and beyond

Again, the limit on the use of run-time annotations is proportional to the developer's creativity.

Considerations

The greatest care every developer needs to take, in my experience, is to pay attention to the fact that annotations are "static". This means that if a given annotated element can have a function at one time and another function at another time, it may be the case to use an external configuration.

Just to cite an example, if you used annotations to configure Dependency Injection with @Autorired and then decided to change the injected object by a subclass, you will need to recompile the code by adding a @Qualifier. With XML configuration, you wouldn't need it. So, there are some cases where XML configuration gives greater flexibility for managing the application outside the application environment. development.

In any case, annotations are an extremely powerful and flexible feature of the Java platform. They are metadata that can be read by frameworks and libraries at the expense of configuration via XML and Imperative Programming.

 13
Author: utluiz, 2014-05-29 13:44:38

Annotations is a powerful tool, and its greatest power is to be able to" configure " objects without the need to know the content and formation of the class.

I will use the classic example in explanation of Annotation (at least I always use this one).

When we use the JTable we have to configure a tableModel, the default is horrible so we usually create one for each table that we are going to present, right?

With Annotations we can create a tableModel configurator without the need to know during its creation, fields, objects or things that we need to put in it.

Thus we create a tableModelGenerico that through reflection it will look in a class indicated what it should consider as columns, even size of the fields, formatting, colors, etc.

EX.

I created my class

Classe {

  private int ID;
  @TableLineCor(GREEN)
  @Coluna(Nome='Nome')
  private String Nome;

  @Coluna(Nome='Data de Nascimento')
  private Date Data;

//gets and sets.

}

So what happened here, when your tableModelGenerico receives as parameter this class and through reflection it reading will already know that you will receive a list of objects of this class, where the row has to be green, that you will have a column called Name that will receive the data of the name property and that you will have another column called Date of birth and that you will receive the data of the date property.

So that way, the Annotations allowed you to create something very generic and that won't need to be rewritten when something changes in the scenario.

I believe that this is one of the most important functions of Annotations.

 2
Author: Marcelo Vasconcelos, 2014-05-29 12:15:16

Just to complement the other answers, I think I can give a good practical example that helps to understand some things explained above:

As we already know, one of the utilities of annotations is to help decrease some settings. The example that comes to mind was when the Servlet specification was changed with the release of Java EE 6 ( JSF315 ). Before Version 3.0, it was all mapped within the web.xml, and in the new specification, just with an annotation, everything is solved internally.

3.0

@WebServlet(value="/oiMundo")
public class OiMundo extends HttpServlet {
        PrintWriter out = response.getWriter();

2.5

<servlet>
   <display-name>Servlet1</display-name>
   <servlet-name>Servlet1</servlet-name>
   <servlet-class>test.Servlet1</servlet-class>
   <init-param>
     <param-name>sleep-time-in-seconds</param-name>
     <param-value>10</param-value>
   </init-param>
   <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
   <servlet-name>Servlet1</servlet-name>
   <url-pattern>/Servlet1</url-pattern>
 </servlet-mapping>
 1
Author: Marco Paulo Ollivier, 2014-06-04 13:45:06