Of Java Annotations

Drawbacks and drawfronts


The J2SE 5.0 release of Java introduced many new language features, one of which is called annotations. At the time I noted their presence, but did not feel particularly excited about their appearance. Now that a little water has flowed under the bridge, I think it is time to revisit Java Annotations.

In this column we will look at what a Java annotation is, what they are used for, how you actually use them in your Java code an dhow you can define your own. We will follow this by considering some of the drawbacks of Java annotations.

Java Annotations

Annotations are presented as metadata – that is data about data. In the case of Java this means that they provide information about various elements of a Java class. For example, they may annotate a method, class or instance variable. One example of an annotation is to note that a method has been deprecated, or that it overrides a method in the superclass. These annotations can then be used by an annotation processing tool (such as APT), or an IDE (such as Eclipse) or indeed a framework, to validate, configure or add to the original Java. For example, if you have annotated a method as overriding a parent class method, then the annotation processing can confirm that you are indeed overriding a method.

There are seven annotations provided in the J2SE 5.0 release (see the annotations guide here; these are provided in two packages, java.lang and java.lang.annotation:

In the package java.lang there is:

@Deprecated – indicates that the associated Java element has been deprecated. It is an alternative to using the Javadoc @deprecated element. A deprecated method or class is essentially one that should no longer be used and that is not guaranteed to be available in future versions of the software. It is thus often useful to know that you are using “old” versions of an API. Although the use of the Javadoc tag already allows many tools (such as Eclipse) to indicate that a language feature is deprecated, the use of the @Deprecated annotation makes this simpler and allows a wider range of tools to report on the use of deprecated features.

@Override - indicates that the method should override a method in the superclass.

@SuppressWarning – directs the compiler to suppress the specified warning.

In the package java.lang.annotaiton:

@Documented – directs tools to automatically generate Javadoc for the annotated element (e.g. a method or variable).

@Inherited – this indicates that the associated annotation is inherited by subclass of the current class.

@Retention – indicates how long annotations with the annotated type are to be retained. For example, a retention type of RUNTIME indicates…

@Target – This indicates the Java element to which associated annotations apply.

It is also possible to extend the set of annotations available by defining your own annotations. This enables project, task and company specific annotations to be created.

What are annotations for?

Annotations are intended to provide three basic facilities. These facilities are:

• The provision of additional semantics for various class elements. This additional semantic information can help developers to understand the intent behind some feature or implementation detail.

• The execution of additional compile time checks that ensure various constraints are met.

• The support of additional code analysis by annotation-aware tools.

None of these requirements are new and indeed many developers have found ways of overcoming the lack of any annotation-like feature in previous versions of Java.

For example, I have tended to make extensive use of Marker Interfaces over the last few years. These are interfaces that may not contain any methods, but are used to denote a particular concept or entity within an application. This is not a particularly radical idea and indeed there is an example of such an interface in the Java language itself - the java.io.Serializable interface. This interface is a marker interface in that it does not require any methods to be implemented but indicates that a class is capable of being serialized via the Java Serialization mechanism.

Such marker interface can now be replaced with annotations. We can define our own annotation that can be used to mark a class as being a particular concept or entity etc.

Using annotations

Annotations are straightforward to use; they merely require that an appropriate annotation type be placed directly before the Java language element being annotated. For example:

public class Person {
@Override
public String getName() {
    return this.name;
}
}

This means that when this code is compiled, or when it is analysed by tools such as Eclipse, a check can be made to ensure that the method getName() does override a method in the class Person’s superclass. In this particular case, the class Person extends the class Object as a default. The class Object does not contain a method getName() and thus it does not override such a method. This therefore results in an error message being generated. For example, in figure 1 Eclipse has identified that the method getName() should override a method in the parent class and has provided a pop up to this effect.

Screenshot showing Eclipse analysing annotations

However, marking which methods you expect to override parent class methods is probably a step two far for many developers. A rather more useful annotation may be the @SuppressWarnings annotation.

The @SuppressWarnings annotation can be very useful if you have some code that uses a deprecated method or class (possibly because it has been in your system since before that method was deprecated) and you do not want the compiler to churn out lots of warnings about using deprecated APIs. By using the @SuppressWarning annotation and the parameter value “deprecation” it is possible to suppress (turn off) the production of the deprecated warning. For example:

@SuppressWarnings("deprecation")
public static void terminateProcess() {
    Thread.currentThread().stop();
}
 

Defining your own annotations

You can easily create your own annotations by defining a new annotation type. This is done using a new piece of language syntax, the @interface key word. For example, to define a new annotation @Auditor we would define the following annotation type.

public @interface Auditor {
    
}
 

Note that although the syntax for this is almost exactly the same as for a standard interface, the “@” symbol at the start of the keyword changes this to be an annotation declaration. When you compile the resulting Auditor.java file this creates a standard Auditor.class file. If you place this class file on your class path, then you can use this new annotation type within your Java code. For example, if you place the @Auditor just before the class declaration, this marks the class as being of the entity type Auditor. This is illustrated in Figure 2.

A screenshot showing the use of the @Auditor annotation

You can also define parameters that can be used with annotations, and accessor methods for retrieving information about the options specified with an annotation.

Drawbacks of Annotations

Annotations are not without their drawbacks. Not least of which is that they are not really metadata – that is they are not data about data – they are data about classes, methods, instance and static variables etc.

Window dressing

As such annotations are syntactic sugar – they coat the elements of a class without actually telling you anything in detail about that class (you can use the reflection API for some of that). Thus they provide guidance to processors, tools and frameworks to help in the analysis, compilation or deployment of that software.

Inheritance

One of the major features of an object-oriented system is inheritance. You can subclass a class, and subclass an interfaces – but you can’t subclass annotations.

Null values

If a null value should be treated as an un-initialized value then annotations are somewhat awkward in the way they handle these – rely on the developer to provide a way of indicating un-initialised rather than initialised to null.

Values in General

These are somewhat limited in what you can use – although in the main this is fine.

Annotations hold constants

The values used with annotations are hard coded rather than variable. Thus if an annotation takes a literal value of 40 – then that value is now hard coded into your program.

Annotations and code synchronization

Just as with Javadoc comments themselves, annotations need to be maintained to reflect any code changes that may occur. However, as we all know, it is all too easy to change the source code and not to update the associated Javadoc (even when they are next to each other). Exactly the same is true for annotations. If the code relating to an annotation changes, then the associated annotation may also need modification. This may not be as straightforward as it seems. For example, if I rename a method in a class I am working on, then this may impact on another class, that I may know nothing about; if that class requires that one of its methods overrides mine (due to the use the @Override annotation). Of course this may be what is desired or it may not! As you can define your own annotations this situation may become much worse, with significant repercussions for on-going maintenance, clarity and general stability of the code.

Summary

So where does that leave the question “To Annotate or not to Annotate?”. In essence, as with many things in life, annotations can be very useful but should not be over used or abused. They can add extremely useful additional information to Java code that can be analysed by tools, frameworks, analysers as well as developers themselves – but they should not be used without due consideration. ®

Further reading

A discussion of Annotations here.

A critique of Annotation weaknesses here.


Other stories you might like

  • Old school editor Vim hits version 9 with faster scripting language
    All of the famed user-friendliness and ease of use, but 'drastically' better performance

    Old school editor fans, rejoice: some two and a half years after version 8.2, Vim 9 is here with a much faster scripting language.

    Vim 9 has only a single big new feature: a new scripting language, Vim9script. The goal is to "drastically" improve the performance of Vim scripts, while also bringing the scripting language more into line with widely used languages such as JavaScript, TypeScript, and Java.

    The existing scripting language, Vimscript, remains and will still work. Only scripts beginning with the line vim9script will be handled differently. The syntax changes are relatively modest; the important differences are in things like local versus global variables and functions, and that functions defined with :def will be compiled before they are run. This allows many errors to be caught in advance, but more significantly, compiled functions execute from 10× to 1000× faster.

    Continue reading
  • Iceotope: No need to switch servers to swap air-cooled for liquid-cooled
    Standard datacenter kit just needs a few tweaks, like pulling off the fans

    Liquid cooling specialist Iceotope claims its latest system allows customers to easily convert existing air-cooled servers to use its liquid cooling with just a few minor modifications.

    Iceotope’s Ku:l Data Center chassis-level cooling technology has been developed in partnership with Intel and HPE, the company said, when it debuted the tech this week at HPE’s Discover 2022 conference in Las Vegas. The companies claim it delivers energy savings and a boost in performance.

    According to Iceotope, the sealed liquid-cooled chassis enclosure used with Ku:l Data Center allows users to convert off-the-shelf air-cooled servers to liquid-cooled systems with a few small modifications, such as removing the fans.

    Continue reading
  • Gartner predicts 9.5% drop in PC shipments
    Stark contrast to 11 percent increase year-over-year in 2021 shipments

    The party is over for PC makers as figures from Gartner suggest the market is on course for a breathtaking decline this year.

    According to the analysts, worldwide PC shipments will decline by 9.5 percent, with consumer demand leading the way – a 13.5 percent drop is forecast, far greater than business PC demand, which is expected to drop by 7.2 percent year on year.

    The PC market in the EMEA region is forecast to fare even worse, with a 14 percent decline on the cards for 2022. Gartner pointed the finger of blame at uncertainty caused by conflicts, price increases and simple unavailability of products. Lockdowns in China were also blamed for an impact in consumer demand.

    Continue reading
  • Samsung beats TSMC to be first to produce 3nm chips
    Lower power consumption, improved performance, and a second generation of the technology on the way

    Samsung has started production of chips using its 3nm fabrication process, beating rival TSMC, which expects to begin making chips with its N3 node generation later this year.

    The resultant chips are claimed to reduce power consumption by up to 45 percent and improve performance by up to 23 percent, with further gains promised in a second generation of the process.

    Korea's electronics giant said it has started initial production with its 3nm process node, which introduces what the firm calls Multi-Bridge-Channel FET (MBCFET) technology. This is Samsung's version of the Gate-All-Around (GAA) transistor architecture, where the gate material wraps around the conducting channel.

    Continue reading

Biting the hand that feeds IT © 1998–2022