Annotate your code to find more bugs

DZone 's Guide to

Annotate your code to find more bugs

· Java Zone ·
Free Resource

We've talked about protecting your reputation with Static Code Analysis recently. In this article we'll build on that technique and show some of the JSR-305 annotations, which can help IntelliJ IDEA spot even trickier issues in your code and so help you save your career of a skilled professional developer.

To briefly recap the story, IntelliJ IDEA comes with a built-in powerful Static Code Analysis engine. This smart engine eagerly scans your code in the background while you think or type, builds an Abstract Syntax Tree (AST) from the code and then searches for known bugs, problems, style rule violations and such in the AST. Found problems get instantly highlighted in the editor for you to fix them. Immediately while you still remember the code and what it does. With static code analysis you typically get rid of many bugs long before you save the file, compile the project and run unit tests.

The JSR-305 proposal suggests several helper annotations, like @Nullable, @NotNull or @Tainted for you to mark certain meta-information in your code. You are able to specify constraints which hold true for a particular method, field, parameter or variable. For example, you can indicate that a particular method may return null and so help the inspection engine to search for potential NullPointerException being raised from your code.

Can you see the warning? Since getName() may return null, the code is incorrectly handling a potentially null value in the name field.

Marking the same method with @NotNull will remove the warning since now your code is free to assume that name doesn't contain a null value and so the NullPointerExceptions cannot happen.

A wise move is to let the @Nullable and @NotNull annotations to influence run-time behavior of the application.

After checking the "Add @NutNull assertions" checkbox in the compiler settings, IntelliJ IDEA will enhance the generated byte-code with checks for null values wherever the @NotNull annotation is used and let the code throw IllegalArgumentException if the @NutNull rule gets violated. You don't get a nasty NullPointerException somewhere far down the road, but instead the application fails with an exception showing the exact spot in your code, where to start searching for the problem - the place, where your expectation expressed via the annotation doesn't match the reality.

Internationalization issues

Let's move on to the next handy fellow - the @NonNls annotation can be used to mark string values as not being locale-sensitive. Since IntelliJ IDEA wants to help you create localized applications, it can complain whenever you try to use a hard-coded String value in an internationalization-sensitive context. By marking a field or parameter as @NonNls you indicate that hard-coded non-localized values can be accepted.

Property files

On a similar note, you can also declare a variable as @PropertyKey and so the engine can check whether the value stored in the variable refers to a valid key in the given property file. And once the meta-information is available, obviously it will be used for your further benefit - to populate a completion dialog for you, if you press Control + Space.

Custom patterns for String values

With the @Pattern annotation you make sure the annotated element always contains a String value matching the supplied regular expressions.

The @Pattern annotation has two helpful children - the @PrintFormat and @Identifier annotations. They are two pre-defined special cases of the @Pattern annotation.
And yes, you are right - defining your own derived annotations is a breeze:

public @interface Number { }

Embeded languages

Last but not the least, we've talked already earlier about language injection with the @Language annotation. Check it out, it is very useful if you combine technologies and languages in your projects.

All combined

So now imagine using these annotations combined in your code. Although you have to add the annotation into your code, in many scenarios they can help you actually reduce the overall amount of code you have. The following method triples a number that comes in a String variable. Notice the amount of code that merely checks whether the value is really a not-null positive integer value.

    public static String triple(final String value) {
try {
if (value != null) {
final int number = Integer.parseInt(value);
if (number<=0)
throw new IllegalArgumentException("The argument must contain a positive integer number");
return "" + number*3;
} else {
throw new IllegalArgumentException("Null values are not allowed");
} catch (NumberFormatException e) {
throw new IllegalArgumentException("The argument must contain a positive integer number");

Using the @NotNull and @Pattern annotations we can reduce the above method to this:

    public static String triple(@NotNull @Pattern("[0-9]+") final String value) {
return "" + Integer.parseInt(value) *3;

This is a space-saver, isn't it. Also, the method signature now explicitly states, what values are expected, the inspection engine will highlight all attempts to pass invalid values into the method and yet we got code, which is clear at the first glance about what it actually does.


The annotations.jar file that comes with all IntelliJ IDEA distributions contains the definitions of the annotations we looked at. As long as you keep the file on your project classpath, neither your Continuous Integration server nor the other IDEs will complain about them. However, only IntelliJ IDEA and TeamCity can currently leverage the annotations to your full benefit.


Now this is it for today. We've looked at a couple of standard JSR-305 annotations, which can help the Static Code Analysis engine find more bugs in our code.

Have fun finding bugs in your code!



Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}