Tuesday, May 17, 2016

Expressing Intent in Annotations

So lets talk Java Annotations for a bit. Specifically how they can apply to Android.

Annotations were added waaayy back when, something like Java 1.5 in 2004. You probably have noticed them strewn about your code already in the form of @Override in front of some of your functions.

Annotations are useful and neat and are relatively lightweight. While not necessary, they can save you headaches down the line when you are designing a large application or designing with a team. Many popular libraries rely on powerful Java Annotations to do things like dependency injection and mocking for tests, and so some developers seem to view annotations as just another way to declare things in Java.

While these annotation based libraries are very useful, I've found one commonly overlooked thing about annotations is the ability to use them to check for basic code mistakes and simplify usage of various functions around the project.

Lets focus for a bit on three annotations included in the Android support library, @NonNull, @Nullable, and @CheckResult.

@NonNull declares that the variable annotated with it should not be null. This would allow you to remove checks in your code that would check for the existence of the object, at least in the scope that it is referenced as @NonNull. It will throw up a lint warning if a null check is performed on a @NonNull variable.

@Nullable does the opposite of @NonNull, declaring that the annotated variable can be null, and will give out a lint warning if its usage is not guarded.

Note that both @NonNull and @Nullable do not throw up any compile time errors if the annotation contract should be violated. This means it is possible for you to pass a null argument into a @NonNull field, but you will get lint warnings when you attempt to do so. Similarly, even though you pass in an argument that is @NonNull, if the actual function you are passing that argument to specifies it as @Nullable, you will need to guard its access anyway. These annotations do not protect you from stupidity or bad programming practices, but they can make it easier to detect potential bugs in the code.

@CheckResult is slightly different in that it can show a lint error if the annotation contract is not respected. @CheckResult should only be applied to functions, and it will cause lint to throw an error if the return value of that function is not used in some way. It can be very useful in distinguishing between functions that return a value and those that do not. In many cases unless you are constructing a public API, my personal preference is to annotate any function that does not return void with @CheckResult.

There are many other useful annotations provided just by the Android support library.  Take a peek at them here.

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================