What is the purpose of annotations in Java? - java

I understand that annotations serve a purpose to modify code without actually BEING code, such as:
#Author(
name = "Benjamin Franklin",
date = "3/27/2003"
)
But I don't understand how using the annotation is any better/ clearer/ more concise than just saying name = "Benjamin Franklin" ? How does the addition of annotations strengthen the code?
EDIT: Sorry for another questoin, but I know that #Override can help prevent/ track spelling mistakes when calling methods or classes, but how does it do that? Does it help the actual program at all?

Annotations are just metadata. On their own they serve little to no purpose. There must be an annotation processor, either at the compiler or run time level that uses them for something.
With an annotation like
#Author(
name = "Benjamin Franklin",
date = "3/27/2003"
)
for example, some annotation processor might read it with reflection at run time and create some log file that this author wrote whatever it's annotating on that date.

Annotations are metadata.
#Override annotation is used to make sure that you are overriding method of a superclass and not just making a method with the same name. Common mistakes here consist of:
spelling the method's name wrong
equal(Object o) instead of equals(Object o)
putting different set of arguments
MyString extends String { public boolean equals(MyString str) {} }
equals(MyString str) is not overriding the method equals(Object o) and therefore will not be used by standard Java comparators (which is used in some standard functions, such as List.contains() and this is prone to error situation).
This annotation helps compiler to ensure that you code everything correctly and in this way it helps program.
#Deprecated annotation doesn't make program not to compile but it makes developers think about using the code that can and/or will be removed in a future releases. So they (developers) would think about moving onto another (updated) set of functions. And if you compile your program with the flag -Xlint compilation process will return with an error unless you remove all usages of deprecated code or explicitly mark them with annotation #SuppressWarnings("deprecation").
#SuppressWarnings is used to suppress warnings (yes, I know it's Captain Obvious style :)). There is a deprecation suppression with #SuppressWarnings("deprecation"), unsafe type casting with #SuppressWarnings("unchecked") and some others. This is helpfull when your project compiler have a compilation flag -Xlint and you cannot (or don't want to) change that.
There are also annotation processors that you integrate into your program build process to ensure that program code meets some sort of criteria. For example with IntelliJ Idea IDE annotation processor you can use #Nullable and #NotNull annotations. They show other programmers when they use your code so that can transfer null as a certain parameter to a method or not. If they transfer null it will cause exception during compilation or before executing a single line method's code.
So annotations are quite helpful if you use them to their full potential.

Annotations are most likely used by other programs. Examples include:
#Override
IDE (compiler?) ensures that the signatures match
#Deprecated
IDE marks occurences, compiler warning
#FXML
JavaFX can use these annotations initialize variables in a controller class when an .fxml File is inflated (see http://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm). They are also used by JavaFX Scene Builder.

Annotations works as a way to marking up the code. Several frameworks uses it, and some others make a great use of it producing your own.
Besides, is important to understand that annotations are the equivalent to meta-data, but is much more than that, since it works as a tag language for the code.

Java #Annotation
#Annotation(from Java 5) adds a metadata which are used for instruction in compile, deployment and run time. It is defined by RetentionPolicy
RetentionPolicy defines a lifetime
RetentionPolicy.SOURCE: It is visible only in compile time(#Override, #SuppressWarnings, #StringDef). For example it can be used by apt to generate some code
RetentionPolicy.CLASS: It is visible in compile and deployment time(.class). For example it can be used by ASM or Java AOP paradigm like AspectJ
RetentionPolicy.RUNTIME: It is visible in deployment and run time. For example it can be used java reflection using getAnnotations(). Dagger 2 uses #Scope annotation
Create a custom Annotation
#Retention(<retention_policy>) //optional
#Target(<element_type>) //optional to specify Java element like, field, method...
#Inherited // optional will be visible by subclass
#Documented // optional will be visible by JavaDoc
#interface MyAnnotation {
//attributes:
String someName();
}
using
#MyAnnotation(someName = "Alex")
public class SomeClass {
}

Related

Compile-time annotation processing

Is there way to do compile-time annotation processing in Java?
Consider this example:
#Name("appName")
private Field<String> appName;
public void setAppName(String name) {
appName.setValue(name);
}
public String getAppName(String name) {
return appName.getValue();
}
public void someFunction() {
String whatFieldName = appName.getName();
}
Where the annotation Name will be processed at compile-time to set the value for Field That is without the common runtime annotation processing. As such, when appName.getName(); (the Field) is accessed it will return the typed value.
Yes, there is, but, no, it cannot change existing files. You can 'plug in' to the compiler and be informed of any annotations; as part of this, you can see signatures (so, field declarations, method signatures, types, etc) but no contents (so not the expression used to initialize a field, and not the contents in the {} of a method declaration), and you can make NEW files, even java files, but you can't edit existing ones.
Project Lombok does edit them, but that is quite the framework to make that possible.
There are some crazy tricks you can use. Project lombok uses one trick (reflect its way into compiler internals, fix everything from there, install agents and plugins in IDEs). Another trick is to use a java source file as a template, of sorts. You name your class some funky (so if you want, say, public class AppDescriptor, you'd actually make the java file AppDescriptorTemplate.java and put public class AppDescriptorTemplate inside. This file has the annotation precisely as you pasted. Your annotation processor can then, during compilation, generate AppDescriptor.java, writing the impls of all methods as simple pass-throughs (a field of type AppDescriptorTemplate is generated, and all methods in ADT are copied over, and the implementations are all one-liners that just invoke that method on the template class). The template class can be package private. In this specific scenario it sounds like you can generate virtually the whole thing based off of pretty much only "appName", though.
Lombok plugs straight into the build and is therefore virtually entirely transparent, in the sense that you simply type in your IDE and the methods it generates just appear as you type, whereas 'normal' annotation processors that e.g. use the XTemplate trick do not work that way and require the build system to kick in, every time. It can be a bit of a productivity drain.

Does Reflections library ignore the RetentionPolicy

For understanding of the Java annotations I tried some hands on and got few doubts, even though looking at execution I am still confused. Here is what I am doing.
Define a Annotation
#Retention(RetentionPolicy.CLASS)
#Target(value=ElementType.TYPE)
public #interface Command {
}
Now I initialize the commands
Reflections reflections = new Reflections(CMDS_PACKAGE);
Set<Class<?>> allClasses = reflections.getTypesAnnotatedWith(Command.class); // line 2
for (Class clazz : allClasses) {
MYCommand cmd = (MYCommand) clazz.newInstance();
System.out.println(cmd.getClass().getAnnotation(Command.class));// line 6
log.info("loading Command [ {} ]", clazz.getCanonicalName());
}
when I run the program line 6 displays null.
When the policy is RetentionPolicy.RUNTIME line 6 displays the correct Command.
During this process the line 2 is still giving me correct Annotated class irrespective of policy. So does it mean that the Reflection Library is ignoring the RetentionPolicy
I am really confused even though reading most of tutorials.
The question for me actually is that , why is this different behaviour? When annotated with RetentionPolicy.CLASS policy It should not have given me at runtime. Is my understanding wrong or can anyone please share there valuable inputs on the understanding of these both.
Yes, the Reflections library (not Reflection, but Reflection*s*) does ignore the visibility of annotations by default.
This can be changed using the org.reflections.adapters.JavassistAdapter#includeInvisibleTag flag. Something like:
JavassistAdapter mdAdapter = new JavassistAdapter();
mdAdapter.includeInvisibleTag = false;
new Reflections(new ConfigurationBuilder()
...
.setMetadataAdapter(mdAdapter)
...
Another option would be to use the JavaReflectionAdapter instead.
HTH
In the first place, the RetentionPolicy dictates what a conforming compiler has to do. Annotations with RetentionPolicy.SOURCE do not make it into the class file while the other two, RetentionPolicy.CLASS and RetentionPolicy.RUNTIME, are stored within the class file but using different attributes to allow to make a distinction between them when reading the class file.
The documentation of RetentionPolicy.CLASS says:
Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time. This is the default behavior.
Here, the responsibility is clearly documented, the VM shall not retain them and the Reflection API built into the JRE conforms to it. Though “need not be retained” does not sound like a strong requirement.
But 3rd party libraries like the Reflection Library you are using are free to implement whatever they want when parsing a class file. Since the documentation for the method you have called simply says: “get types annotated with a given annotation”, the behavior isn’t wrong as the type has that annotation.
And you are able to find out the RetentionPolicy of that Annotation even before invoking that method by analyzing the Annotations of the Annotation. So it makes no sense invoking the method when you already know that the annotation has the RetentionPolicy.CLASS and then bother because the method does something instead of nothing.
But, of course, it would be better if that behavior was documented completely. So you might ask the author of that 3rd party library to improve the documentation.

How to indicate that member fields are #Nonnull by default?

My question is a follow-up to this one.
In past versions of FindBugs, it was possible to use #DefaultAnnotation(Nonnull.class) or #DefaultAnnotationForFields(Nonnull.class) to indicate that all fields in a package should be treated as #Nonnull. In the current version of FindBugs (2.0), #DefaultAnnotation and #DefaultAnnotationForFields are deprecated, and we should all use JSR-305 instead. But JSR-305 doesn't seem to cover everything the (now deprecated) FindBugs annotations cover.
The javadoc does suggest a number of alternatives:
#ParametersAreNonnullByDefault. This (obviously) only applies to parameters, not to member fields.
#CheckReturnValue, when applied to a type or package. Again, this doesn't apply to member fields.
#TypeQualifierDefault. Maybe this can do what I want, but I don't understand how it works, and I'm unable to find any documentation or examples on its usage or intent, besides some cryptic javadoc. I think it will help me create my own annotations, but can I be sure that all the tools (FindBugs, Eclipse, etc.) will interpret this new annotation correctly (or even at all)?
The javadoc doesn't provide any hints on how to deal with its deprecation.
So, using the current versions of FindBugs and/or JSR-305, how should I indicate that all member fields in a certain package (or even in a certain class) are supposed to be treated as #Nonnull? Is it even possible?
I had a similar question, and found that the following seems to work with findbugs (2.0.1-rc2)
Create a java file with the following annotation definition
#Nonnull
#TypeQualifierDefault(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
public #interface FieldsAreNonNullByDefault
{
}
similarly, to enforce that all return values from a method are non-null
#Nonnull
#TypeQualifierDefault(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface ReturnTypesAreNonNullByDefault
{
}
and then annotate the package as normal.
I used the following for my tests (package-info.java)
#javax.annotation.ParametersAreNonnullByDefault
#com.habit.lib.lang.FieldsAreNonNullByDefault
#com.habit.lib.lang.ReturnTypesAreNonNullByDefault
package com.mypackagename.subpkg;

Search for all instances of certain annotation type

Suppose I have this annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface Name
{
String value();
}
This is going to be used as follows
#Name("name1")
public static Foo foo = new Foo();
I have multiples of these across my project source files. Is there an fairly simple way to search and collect all those "foo"s that're preceded by #Name?
In other words, I'd like to write a method that would return a Set<Foo> containing these.
Thanks!!!
I am not really familiar with the classpath scanners that others are suggesting. They seem like a robust - if not ideal - solution.
If you have control over the source, then you could use annotation processing.
Create an annotation processor that will create a class - MapClass with a static member Map<String,Foo>. Every time the annotation processor encounters the #Name annotation, it adds that to the source code of MapClass. When it finishes processing the annotations, it will have the same effect as if you hard coded the map.
Annotation processing happens during compile time. If some of the classes in your project are not compiled by you. For example, if someone else compiles some classes and gives a jar to you, then it won't work as easily. But if all the classes are compiled by you then it should not be a problem.
To create an annotation processor, extend AbstractProcessor. You will want to annotate your class with a # SupportedAnnotationTypes ( "Name" ) annotation (make sure name is the fully qualified name of your annotation.
Override the process method. process has two parameters: annotations and roundEnv. annotations is just the set of annotations that this particular processor supports - in your case it should be (Name). roundEnv is a useful utility class.
Iterate through the one annotation in annotations. Use roundEnv to getElementsAnnotatedWith. This should give you the set of all elements that carry the #Name annotation.
AbstractProcessor has another utility member - processingEnv. Use its getFiler method to createSourceFile.
Then you have to modify your compilation a little bit. You must compile your processor separately and before the other classes. After the processor is compiled and you are compiling the other classes you must tell the compiler about your processor. If you are using the command line you would add -processorpath /path/to/processor/class[es] and -processor qualified.name.of.processor.
The advantages of this approach over the class path scanner is that everything happens at compile time. So for example, if you accidentally add a #Name annotation to a Bar element, then you can have the processor throw a compile time error (if you wish the processor can ignore it). Then you can fix it before the product ships. With a class path scanner, any error thrown is a run time error - which the user will see.
The disadvantage of this approach is also that everything happens at compile time. This makes it harder to dynamically add classes to the project.
What you need is a Classpath scanner. I have used Metapossum Scanner (it won out because it is in the mvn repo) to scan for annotated Classes, but I do not think it would scan for annotated Fields.
The other option I looked into was Reflections. I have not used Reflections, only researched it. The documentation has a getFieldsAnnotatedWith query that seems like what you need.
Be forewarned, the Classpath scanners are slooow and get slooower the more you have in your Classpath.
No not really (not from code).
A solution would be to put them all in a class, and then iterate on the Fields (getFields()) of the class and check for Annotations (getAnnotation())
You may want to have a look at Scannotation! It may solve your problem!!!
Scannotation is a Java library that creates an annotation database from a set of .class files. This database is really just a set of maps that index what annotations are used and what classes are using them.
PS.: VRaptor framework uses it internally!

How compiler deals with annotations?

I have some questions about working of annotations in java.
If annotations cannot be converted to bytecode then where does this information go?
where does the meta-data goes?
How Java Reflection uses this information?
How compiler deals with annotations?
When we say,
#Override
public void doSomething(){
}
What does a java compiler do with it?
I know that it checks the method signature so that the method should be a perfectly overridden method, but how?
There are three types of annotations see http://download.oracle.com/javase/6/docs/api/java/lang/annotation/RetentionPolicy.html
#Override is a special case as the compiler does additional checks.
#Override is a source type annotation - used to check if a particular method follows the contract of an overriden method - hence it isn't available at runtime (and therefore logically doesn't exist in the compiled bytecode).
I know that it checks the method signature so that the method should be a perfectly overridden method, but how
In the process of reading the source files and converting them to bytecode, e.g., not using reflection at all. See The Java Programming Language Compiler - javac for additional compiler information.
Annotations have a RetentionPolicy, which specifies if the annotation will be stored in the class file (RetentionPolicy.CLASS, RetentionPolicy.RUNTIME) or will be discarded by the compiler (RetentionPolicy.SOURCE).
The #Override method has a RetentionPolicy of RetentionPolicy.SOURCE (meaning it is discarded by the compiler and not available at runtime via Reflection) and a target of ElementType.METHOD (meaning that this method can only be annotated on method declarations only).
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.SOURCE)
public #interface Override {
}
Only annotations with a RetentionPolicy of RetentionPolicy.RUNTIME can be read by Reflection.
At first, there were 2 kinds of annotations: Runtime accessible (2 kinds) and not runtime accessible. The behavior of annotation is done by retention policy through annotation of annotation declaration :-). Example:
#Retention(RetentionPolicy.RUNTIME) // effectively visible to JVM Runtime
public #interface MethodInfo {
String author() default "unspecified";
String lastModification() default "unspecified"; // Format: yyyy-mm-dd
ImplementationStatus implementationStatus();
}
JVM runtime visible annotations can be accessed through reflection during annotated code execution (or when it is loaded by the JVM). You utilize those annotations as metadata holders. Metadata can be processed by other code to do various things eg. to check annotated method implementation status before a given method is executed.
But someone must write code to use the annotation matedata through reflection! The best example is an application server (AS) that loads classes on demand from JAR files placed is some particular directory. AS can contain code that checks each loaded class for static methods annotated by the #Initialization annotation and executes those methods right away. This annotation type is defined by AS and those who create JARs and classes for AS use it during development.
Annotations that are not available during runtime are used and worked out during compilation. #Override is good example. Custom source only annotations can be used by compiler plugins or if code is compiled by other code on demand.
This one is simple. Compiler just checks the super class for method with same name and same number of parameters, their order and types. If method has #Override annotation and such method hasn't been found an error is generated.
More interesting question is how compiler deals with annotations which has mean at runtime. I assume they are added in byte-code but in some special section with meta information. So, in runtime jvm has access to the meta section. As a prove, you can always call getAnnotations() on any class object.
Compiled annotations (which are ultimately constant data) live the class file and can be accesses with the appropriate methods getAnnotations() and friends.

Categories

Resources