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.
Related
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.
C# 6.0 introduced the nameof() operator, that returns a string representing the name of any class / function / method / local-variable / property identifier put inside it.
If I have a class like this:
class MyClass
{
public SomeOtherClass MyProperty { get; set; }
public void MyMethod()
{
var aLocalVariable = 12;
}
}
I can use the operator like this:
// with class name:
var s = nameof(MyClass); // s == "MyClass"
// with properties:
var s = nameof(MyClass.OneProperty); // s == "OneProperty"
// with methods:
var s = nameof(MyClass.MyMethod); // s == "MyMethod"
// with local variables:
var s = nameof(aLocalVariable); // s == "aLocalVariable".
This is useful since the correct string is checked at compile time. If I misspell the name of some property/method/variable, the compiler returns an error. Also, if I refactor, all the strings are automatically updated. See for example this documentation for real use cases.
Is there any equivalent of that operator in Java? Otherwise, how can I achieve the same result (or similar)?
It can be done using runtime byte code instrumentation, for instance using Byte Buddy library.
See this library: https://github.com/strangeway-org/nameof
The approach is described here: http://in.relation.to/2016/04/14/emulating-property-literals-with-java-8-method-references/
Usage example:
public class NameOfTest {
#Test
public void direct() {
assertEquals("name", $$(Person.class, Person::getName));
}
#Test
public void properties() {
assertEquals("summary", Person.$(Person::getSummary));
}
}
Sadly, there is nothing like this. I had been looking for this functionality a while back and the answer seemed to be that generally speaking, this stuff does not exist.
See Get name of a field
You could, of course, annotate your field with a "Named" annotation to essentially accomplish this goal for your own classes. There's a large variety of frameworks that depend upon similar concepts, actually. Even so, this isn't automatic.
You can't.
You can get a Method or Field using reflection, but you'd have to hardcode the method name as a String, which eliminates the whole purpose.
The concept of properties is not built into java like it is in C#. Getters and setters are just regular methods. You cannot even reference a method as easily as you do in your question. You could try around with reflection to get a handle to a getter method and then cut off the get to get the name of the "property" it resembles, but that's ugly and not the same.
As for local variables, it's not possible at all.
You can't.
If you compile with debug symbols then the .class file will contain a table of variable names (which is how debuggers map variables back to your source code), but there's no guarantee this will be there and it's not exposed in the runtime.
I was also annoyed that there is nothing comparable in Java, so I implemented it myself: https://github.com/mobiuscode-de/nameof
You can simply use it like this:
Name.of(MyClass.class, MyClass::getProperty)
which would just return the String
"property"
It's also on , so you can add it to your project like this:
<dependency>
<groupId>de.mobiuscode.nameof</groupId>
<artifactId>nameof</artifactId>
<version>1.0</version>
</dependency>
or for Gradle:
implementation 'de.mobiuscode.nameof:nameof:1.0'
I realize that it is quite similar to the library from strangeway, but I thought it might be better not to introduce the strange $/$$ notation and enhanced byte code engineering. My library just uses a proxy class on which the getter is called on to determine the name of the passed method. This allows to simply extract the property name.
I also created a blog post about the library with more details.
Lombok has an experimental feature #FieldNameConstants
After adding annotation you get inner type Fields with field names.
#FieldNameConstants
class MyClass {
String myProperty;
}
...
String s = MyClass.Fields.myProperty; // s == "myProperty"
I am writing a library, so I don't often use the methods in my classes within the same project. As such, my IDE (IntelliJ IDEA) keeps warning me that the methods are unused.
Of course, the obvious solution is to place #SuppressWarnings("unused") before the classes. I don't like this; it doesn't describe the reason I'm writing that annotation and is very verbose. I would love to make an annotation like #LibraryClass which is just an alias of #SuppressWarnings("unused").
In short, I want to be able to change this:
#SuppressWarnings("unused")
public class MyLibraryClass {
public void myLibraryMethod() {
doSomething();
}
}
to this:
#LibraryClass
public class MyLibraryClass {
public void myLibraryMethod() {
doSomething();
}
}
but I have no idea how to do this! I tried all this, and it compiles, but the IDE still warns of unused methods:
#SuppressWarnings("unused")
#Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
#Retention(RetentionPolicy.SOURCE)
public #interface Library {
SuppressWarnings superAnnotation() default #SuppressWarnings("unused");
String[] value() default {"unused"};
}
To do one aspect of what you're asking for - attaching some kind of compile-time logic to annotations - you need to look into annotation processing. An annotation processor hooks into the Java runtime, like an agent, and gets informed about annotations and given an option to process it. To use that, you'd have to put your annotation-processor jar on the IDE's classpath.
Some links:
http://hannesdorfmann.com/annotation-processing/annotationprocessing101
http://programmaticallyspeaking.com/playing-with-java-annotation-processing.html
However, that wouldn't allow you to change the way that Intellij detects unused methods, which seems to be closer to your specific use case. What you could do there is to modify the Intellij 'unused method' inspection so that it incorporates a check for the custom annotation you've defined. YMMV, I've never had to do that at the class level before.
https://gist.github.com/itzg/5e90609cde1473ef9d4d
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.