Does JDK automatically generate proxy classes for custom annotations? - java

Here is my code(JDK1.8):
#Retention(RetentionPolicy.RUNTIME)
#Target(value={ElementType.TYPE})
#Documented
public #interface MyAnnotation {
}
#MyAnnotation
public class Main {
public static void main(String[] args) {
Class<Main> cls = Main.class;
Annotation[] annotations = cls.getDeclaredAnnotations();
Arrays.stream(annotations).forEach(an -> {
if (an instanceof MyAnnotation) {
System.out.println("proxy");
} else {
System.out.println("???");
}
System.out.println(an.getClass().getName());
});
}
}
i test on windows,centos7 and ubuntu got the same result:
proxy
com.sun.proxy.$Proxy1
My question: Is this my environment problem or JDK will automatically generate a proxy class? if it is the latter,why? Thanks in advance.

See 9.6. Annotation Types:
An annotation type declaration specifies a new annotation type, a special kind of interface type."
As interfaces cannot be instatiated directly, there has to be some kind of object implementing that interface that is returned from the reflection API methods. Whether that is a proxy or some other kind of anonymous class is up to the implementation.

Related

Java Annotation how to get current ElemenType of specific annotation

My annotation:
#Target({ElementType.TYPE, ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
public #interface ObjectName {
String name() default "";
String field() default "";
}
Some class with my annotation
#ObjectName("a_")
public class A {
#ObjectName("field_")
String filed;
}
Problem - when i get all my "ObjectName" annotations from class above, how can i get annotation's ElementType value (field, class or method type)?
So i want something like this
public void process(Class<?> clazz) {
Annotation[] annotations = clazz.getAnnotations();
for (Annotation anno : annotations) {
if (anno instanceof ObjectName) {
ObjectName annObjName = (ObjectName) anno;
Target target = anno.getAnnotation(Target.class);
if (target.getType().equals(ElementType.TYPE)
doThat(annObjName.name());
else if (target.getType().equals(ElementType.FIELD)
doThis(annObjName.field());
}
}
}
Can i even do this?
How can i do this or how can i find out if this annotation declared on filed or class?
You can't.
All you can do is look at where you call getAnnotations(), because you seem to incorrectly believe that clazz.getAnnotations() will return all annotations on everything in the class. That is false. When you call clazz.getAnnotations(), you will only get the annotations directly on the class. To get annotations on fields, you must call clazz.getFields(), and then call getAnnotations() on the Field elements. So there's no risk of getting them mixed up as long as you keep those straight.

Guice custom binding annotation fails, but #Named works?

I'd thought that a custom binding annotation #Foo was equivalent in functionality to #Named("foo"). Is this not true?
I've got, in separate GuiceModules, two things providing the same item type:
In GuiceModuleFoo
#Foo
#Provides
public String provideFoo() { return "foo"; }
In GuiceModuleBar
#Bar
#Provides
public String provideBar() { return "bar"; }
class MyOtherThing extends Thing {
#Inject
public MyOtherThing(#Foo String s) {
super(s);
}
}
Further, in case it matters, I'm using Modules.override so that GuiceModuleBar overrides GuiceModuleFoo (for an unrelated provide).
MyOtherThing is not getting injected with the #Foo provided value though. It's getting the value from the #Bar provider. It actually seems somewhat random what provides it when I added a 3rd provider #Baz.
However, when converting everything to use #Named (e.g. #Named("foo")), it works exactly as desired!
So...am I misunderstanding how binding annotations work? The custom annotations looked like this:
#BindingAnnotation
#Target({ FIELD, PARAMETER, METHOD }) #Retention(RUNTIME)
public #interface Foo {
}

Java: obtaining private member's annotations

I'm trying to find all fields annotated with a custom annotation, but it doesn't seem to detect it. The same code works fine for standard annotations, such as #Deprecated.
Minimal code to reproduce:
public class MyClass {
public #interface MyAnnotation {}
#MyAnnotation Object someObject;
#MyAnnotation #Deprecated Object someDeprecatedObject;
#Deprecated Object aThirdObject;
public static void main(String[] args) {
Class<?> cls = MyClass.class;
for (Field field : cls.getDeclaredFields()) {
System.out.print(field.getName());
for (Annotation a : field.getDeclaredAnnotations())
System.out.print(" " + a);
System.out.println();
}
}
}
Output:
someObject
someDeprecatedObject #java.lang.Deprecated()
aThirdObject #java.lang.Deprecated()
#Deprecated comes up, but #MyAnnotation doesn't! Help!
By default, annotations are not kept at runtime and so cannot be reflected upon. You need to declare your annotation like this to ensure it exists at runtime:
#Retention(RetentionPolicy.RUNTIME)
public #interface MyAnnotation {
}

how to print the default value of annotation interface in main java program

I am new with an annotated interface:
#interface
Test {
public String getInfo() default "hi";
}
#test
class TestImpl implements Test
{
public String getInfo(){return getInfo();}
public static void main(String...args)
{
TestImpl impl=new TestImpl ();
impl.getInfo();
}
}
Actually, I am totally confused with this, I want to print the default value of my getInfo() methods. and don't know how to use it and also the advantages of the annotated interface.
if some buddy has an idea about it, plz make changes of my above code as the printable format of default values, and also if it id possible then give me the URL from where I can read more about the annotated interface.
Thanks,
Subodh Ray
class TestImpl { // not implementing the annotation interface
and then:
Test annotation = TestImpl.class.getAnnotation(Test.class);
String info = annotation.getInfo();
Note that usually annotation attributes are not defined as getters. So info() instead of getInfo()
Update: you need #Retention(RetentionPolicy.RUNTIME) on your annotation class. If it is not there, the annotation is not preserved at runtime.

How to use Java annotations rention policy for CLASS

I'm using annotations for generating documentation for an API that I'm publishing. I have it defined like this:
#Documented
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface PropertyInfo {
String description();
String since() default "5.8";
String link() default "";
}
Now this works fine when I process the classes using reflection. I can get the list of annotations on the method. The issue I have is that it only works if I instantiate a new instance of the object I'm processing. I would prefer not to have to instantiate them to get the annotation. I tried RetentionPolicy.CLASS but it doesn't work.
Any ideas?
You don't need to instantiate an object, you just need the class. Here is an example:
public class Snippet {
#PropertyInfo(description = "test")
public void testMethod() {
}
public static void main(String[] args) {
for (Method m : Snippet.class.getMethods()) {
if (m.isAnnotationPresent(PropertyInfo.class)) {
System.out.println("The method "+m.getName()+
" has an annotation " + m.getAnnotation(PropertyInfo.class).description());
}
}
}
}
Starting from Java5, classes are loaded lazily.
There are somes rules that determine if a class should be loaded.
The first active use of a class occurs when one of the following occurs:
An instance of that class is created
An instance of one of its subclasses is initialized
One of its static fields is initialized
So, in your case, merely referencing its name for reflection purposes is not enough to trigger its loading, and you cannot see the annotations.
You can get the annotations for a class using bean introspection:
Class<?> mappedClass;
BeanInfo info = Introspector.getBeanInfo(mappedClass);
PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
for (PropertyDescriptor descriptor : descriptors) {
Method readMethod = descriptor.getReadMethod();
PropertyInfo annotation = readMethod.getAnnotation(PropertyInfo.class);
if (annotation != null) {
System.out.println(annotation.description());
}
}

Categories