I have been given a project that I have to study & understand. There's a class that has the following: -
public abstract class AbstractPayment extends GodelCheckout {
public static final String AUTH_USING_GET = "GET";
public static final String AUTH_USING_POST = "POST";
#Retention(RetentionPolicy.SOURCE)
#StringDef({AUTH_USING_GET, AUTH_USING_POST})
public #interface AuthMethod {}
I tried understanding annotation & why they are important from Google's Developer site, but I couldn't understand much apart from the fact that they are used for improving code.
But how are they improving code? Any example?
Why is #Retention(RetentionPolicy.SOURCE) required here?
What does #StringDef() actually do?
what is public #interface AuthMthod{}?
Please explain what Retention.SOURCE, .CLASS & .RUNTIME really are? I tried understanding them from Google's Developer's site, but it didn't help much?
By marking a function argument or result of it, you can define an expected behaviour. For example it marking a function argument with that annotation, no other argument than AUTH_USING_GET or AUTH_USING_POST can be passed.
With source retention, the code won't compile, when there are annotation errors. After successful compilation, they are removed from code. With retention policy RUNTIME the code is inspected during running.
#StringDef allows you to pass only String id's, for example R.string.login. #IntDef allows you to pass only R.id.sample_int to the function
This is the annotation, that desired parameters or function results or class fields must be annotated to obtain desired result.
Look at second question.
For more questions refer to Java documentation.
Related
Suppose I have a class structure like :
#MyAnnotationOne
class A {
private String id;
private B b;
public static class B {
private C c;
#MyAnnoationOne
public static class C {
#MyAnnotationTwo
private String annotatedString;
}
}
}
I am using annotation processing to generate code. If I'm processing #MyAnnotationOne, then using the Mirror API I can get all the fields in class A and class C.
I want to know if there is any way I could find if any of the fields in class A, going down the hierarchy contain the annotation #MyAnnotationOne or #MyAnnotationTwo. Finding any one would be enough.
I tried looking for a solution but I found some saying that since the annotation processing happens in a pre-compilation stage, the information might not be available. Please let me know if there's any solution that you might know. It'd be a great help.
You can configure whether annotations are retained into runtime or not. You annotate your own annotation type with the java.lang.annotation.Retention meta-annotation, specifying one of the values from the enum java.lang.annotation.RetentionPolicy.
RUNTIME Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.
CLASS Annotations are to be recorded in the class file by the compiler but need not be retained by the VM at run time.
SOURCE Annotations are to be discarded by the compiler.
EDIT
If you are building an annotation processor:
your code is running during that (pre) compilation phase, so all annotations should be present.
Mirror API is deprecated, see javax.lang.model... and javax.annotation.processing
If you override javax.annotation.processing.AbstractProcessor.process() you receive a RoundEnvironment with methods for getting model Elements, including sets filtered by specific annotation types. And given an Element you can getEnclosedElements() and on those getAnnotation(annotationType).
In Java I have the possibility to "implement" annotations.
Sample Java annotation:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface JavaClassAnno {
String[] value();
}
Sample Java "implementation":
class MyAnnotationLiteral
extends AnnotationLiteral<JavaClassAnno>
implements JavaClassAnno { // <--- works in Java
private String value;
public MyAnnotationLiteral(String value) {
this.value = value;
}
#Override
public String[] value() {
return new String[] { value };
}
}
Trying to port that to Kotlin doesn't work as it says that the annotation is final and therefore can not be inherited, i.e. the following will not work:
class MyAnnotationLiteral(private val internalValue: String)
: AnnotationLiteral<JavaClassAnno>(),
JavaClassAnno { // <--- doesn't work in Kotlin (annotation can not be inherited)
override fun value(): Array<String> {
return arrayOf(internalValue)
}
}
How do you "implement/extend" annotations the Kotlin way? Could not find any reason why Kotlin differs in that regard to Java. Any hint how to solve that problem or any sources that tell why it is that way are welcome.
The following question contains a use case for this constellation: Dynamically fire CDI event with qualifier with members.
Basically you require something like this to narrow down which qualifier should trigger based on its members.
Note that this would also apply to a Kotlin annotation as well as it seems that a Kotlin annotation can not be open and therefore not be implemented/extended too.
What I found so far is rather mentioning #Inherited as a problem:
https://discuss.kotlinlang.org/t/inherited-annotations-and-other-reflections-enchancements/6209
https://youtrack.jetbrains.com/issue/KT-22265
But I did not find any reason why the annotation is not implementable/inheritable as it is in Java.
I also asked this question now here: https://discuss.kotlinlang.org/t/implement-inherit-extend-annotation-in-kotlin/8916
Update: Finally I found something regarding this design decision, namely the following issue (while I was opening my own issue for it): Annotations inheritance. Either prohibit or implement correctly. As it seems the decision was to "prohibit" it, even though there are no (visible?) comments, discussions or other sources about that decision.
Added the following issue: https://youtrack.jetbrains.com/issue/KT-25947
As of Kotlin 1.3, this case is not supported. To create custom instances of annotations one has to resort to Java for now. One of the reasons for this design decision is that making annotations interfaces is too JVM-specific and wouldn't map well to other platforms.
I'm trying to understand the use of 'Annotations' a bit better.
I understand that:
How to access annotations in my code for example via this complete tutorial.
I can create methods to perform desired operations
To understand this better, I created a virtual problem as following:
There are Annotations TestAnnotation1, TestAnnotation2, TestAnnotation3(definition is available latter in the question). I wants to execute the methods of class MethodsExecutorClass as following:
When TestClass.java compiles then execute CommonMethod() and RetentionPolicySOURCEMethod()
When TestClass.class loads then execute CommonMethod() and RetentionPolicyCLASSMethod()
Whenever testMethod() method of TestClass.java executes then execute CommonMethod() and RetentionPolicyRUNTIMEMethod()
By this example I wants to understand following:
Can I instruct Java compiler (javac) or Java Runtime Environment (jvm) to execute a method in my class(e.g. CommonMethod()andRetentionPolicySOURCEMethod()methods ofMethodsExecutorClass`).
Can I delegate the monitoring (i.e. searching the methods/classes which are using my annotation etc.) to any other entity(which is available in Java SE).
I want to do something like #Override and #deprecated annotations. We don't do something extra. Although on Oracle javadoc site, here it is clearly mentioned that The Java platform has always had various ad hoc annotation mechanisms. and #deprecated is one of them. But I wondered If I can do something like this.
Definitions should look like as following:
MyAnnotations.java:
#Retention(RetentionPolicy.SOURCE)
public #interface TestAnnotation1
{
String className();
}
#Retention(RetentionPolicy.CLASS)
public #interface TestAnnotation2
{
String className();
}
#Retention(RetentionPolicy.RUNTIME)
public #interface TestAnnotation3
{
String className();
String methodName();
}
MethodsExecutorClass.java:
class MethodsExecutorClass
{
public static void CommonMethod()
{
System.out.println("In method: CommonMethod()");
}
public void RetentionPolicySOURCEMethod()
{
System.out.println("In method: RetentionPolicySOURCEMethod()");
//Also print annotation arguments e.g. Class name etc
}
public void RetentionPolicyCLASSMethod()
{
System.out.println("In method: RetentionPolicyCLASSMethod()");
//Also print annotation arguments e.g. Class name etc
}
public void RetentionPolicyRUNTIMEMethod()
{
System.out.println("In method: RetentionPolicyRUNTIMEMethod()");
//Also print annotation arguments e.g. Class name etc
}
}
TestClass.java:
#TestAnnotation1(TestClass.class)
#TestAnnotation2(TestClass.class)
class TestClass
{
#TestAnnotation2(TestClass.class, "testMethod()")
public void testMethod()
{
System.out.println("In method: testMethod()");
}
}
May you help me in achieving this? (Please no guess or assumptions, but presumptions would be also helpful).
I'm not sure if this can be achieve, but looking forward.
Annotations with retention policy RetentionPolicy.SOURCE are only available during compilation time of the code so your compiler should support your annotation to use it, otherwise it's not possible to handle the annotation. Usually, such annotations are used to detect possible problems at compilation time, for example, annotation #Override. That's why your first problem can't be implemented in usual ways.
Annotations with retention policy RetentionPolicy.CLASS are available only in .class files and can be used via JVMs. Please see this answer how it can be used. The second your problem also can't be implemented via standard ways.
Commonly used annotations are with retention policy RetentionPolicy.RUNTIME that are available via reflection mechanism in Java. But to solve your third problem you have to use some method invocation interceptors, for example, via Aspect Oriented Programming. After that you can get method's annotations via method.getDeclaredAnnotations().
Can I instruct Java compiler (javac) or Java Runtime Environment (jvm)
to execute a method in my class(e.g.
CommonMethod()andRetentionPolicySOURCEMethod()methods
ofMethodsExecutorClass`).
No, you can't.
Can I delegate the monitoring (i.e. searching the methods/classes
which are using my annotation etc.) to any other entity(which is
available in Java SE).
You can do it via AOP, for example, use the library AspectJ.
I'm trying to create an annotation for a local variable. I know that I can't retain the annotation in the generated bytecode, but I should be able to have access to the information at compile time by doing something like this:
#Target({ElementType.LOCAL_VARIABLE})
#Retention(RetentionPolicy.SOURCE)
public #interface Junk {
String value();
}
only, this doesn't get processed by apt, or javac when I specify a ProcessorFactory that has "Junk" in it's supported types in the following:
class JunkTester {
public static void main(String[] args) {
#Junk String tmp = "Hello World";
System.out.println(tmp);
}
}
It will however work when I move the #Junk annotation before public static
Thoughts and or workarounds?
Did some quick tests and searched a little, and it's looking like hooking into LOCAL_VARIABLE isn't really supported...yet:
http://forums.sun.com/thread.jspa?threadID=775449
http://www.cs.rice.edu/~mgricken/research/laptjavac/
https://checkerframework.org/jsr308/
Could be totally wrong, but that's how it's looking...
It seems that the Type Annotations Specification (JSR 308), will hopefully address this subject in the future (JDK 8 ?).
As of Java 8, local variable annotations are stored in the classfile.
A standard Java annotation processor does not process the bodies of methods.
However, the Checker Framework enables you to write an annotation processor that processes every annotation including on local variables. Its annotation processors can even examine every statement of the program, whether annotated or not.
do they by annotation mean a comment in a code with // or /* */?
No, an annotation is not a comment. An annotation is added to a field, class or method, using the syntax #Annotation. One of the best known annotations is #Override, used to signal a method is overriding one from a super class. For example:
public class MyClass {
#Override
public boolean equals(Object other) {
//...
}
}
See http://download.oracle.com/javase/1,5.0/docs/guide/language/annotations.html for more info.
No, annotations take the form:
#Annotation(property="A")
public class {
#Annotation(property="B")
Object field;
#Annotation(property="C")
public void method() {
}
}
Annotations can be placed on classes, methods or fields. They can provide information at runtime via reflection or compile time via apt (short for Annotation Processing Tool and not the apt package manager).
They are defined as:
#interface Annotation {
String property();
}
See http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html for more
Actually, before Java5 (i.e. 1.3 or 1.4), comments (// or /* */) were the only way to add annotation (i.e. "metadata") to be acted upon.
One classic example is the way the unit-testing framework TestNg propose all its Java5 #Annotations as comments if you are using TestNg with Java 1.4.
But that means, for Testng to launch the proper test suite, it had to access the sources of your program, not just the compiled binary.
Unlike Javadoc tags, Java annotations can be reflective in that they can be embedded in class files generated by the compiler and may be retained by the Java VM to be made retrievable at run-time.
No.
An annotation is a special construct introduced with java 1.5. An annotation adds some meta information to a java class, method or variable. This meta information can be evaluated at compile time (e.g. for generating some extra code with apt) or at runtime (e.g. to match a class to a database table).
Example for a built in annotation:
#Deprecated // this is an annotation
public void myMethod() {
...
}
Annotations are not just for java they also exist in c++, they are somehow similar with those from java.
// MyCode.h
# include <CodeAnalysis/SourceAnnotations.h>
using namespace vc_attributes;
class CMyClass
{
public:
void f ( [Pre ( Valid = Yes )] int *pWidth );
// code ...
};
// MyCode.cpp
#include "MyCode.h"
void CMyClass::f ( [Pre (Valid = Yes)] int pWidth )
{
}
You can check the MSDN for more information:
http://msdn.microsoft.com/en-us/library/ms182036(VS.80).aspx
An annotation is not a comment but it is used for many purposes such as error debugging as well it is the instruction set to the compiler but it hasn't any effect on the runtime code.
#override,#deprecated and others are the examples of annotation. It can be used with methods,constructors,parameters,variables.
Annotations are used to give detailed information to the compiler whereas Comments are for the convenience of the programmer so that he know how the code is structured.
of course not, but I think annotation ≈ comment.
the core of them is describe, but annotation has more confinement, you are not easy to make mistak, also, you can find mistake in compile time.