How to read a default value specified in #interface - java

I am trying to understand why I would use #interface. I see many tutorials explaining what all those annotations mean but no where could I find in simple terms how (or why) I can use them.
As a made up example
#Target({ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#Inherited
#Documented
public #interface MyAnnotation {
String getAString() default "blah";
}
Suppose I use this annotation on a class.
#MyAnnotation
public class TestClass {
public String test(){
return this.getAString();
}
}
Can I call getAString() without using reflection?
If not, what can be
a possible use of it?

Here is an example on how you can use annotation fields:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface MyAnnotation {
public String name();
public String value();
}
for(Annotation annotation : annotations){
if(annotation instanceof MyAnnotation){
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("name: " + myAnnotation.name());
System.out.println("value: " + myAnnotation.value());
}
}
The example is taken from here:
http://tutorials.jenkov.com/java-reflection/annotations.html
Also see this:
#interface default declaration usage in Java

Related

Java initialise array of annotations

I'm trying to initialise an array of annotations but can't figure out the syntax.
public #interface Tag {
String key();
String value();
}
#Target({ElementType.ANNOTATION_TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface BaseAnnotation {
String[] names();
Tag[] tags();
}
As you can see, BaseAnnotation has an array of Tag annotation and I want to use it to annotate another annotation like this:
#BaseAnnotation(names={"abcs", "bnm"},
tags = {key="aaa",value="bbb"}) //I can't figure out the syntax for this one
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface ToBeUsedAnnotation {
}
The problem is that I've tried a few ways to set the values for tags but can't find any useful documentation on how to do it.
Thanks.

Java custom annotations takes another annotation

how can I write a custom annotation that takes another annotation and the values?
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface TestAnnotation{
Class<? extends TestAnnotationChild> annotation();
}
The second annotation
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface TestAnnotationChild{
}
And I would like to do something like
#TestAnnotation(#TestAnnotationChild={values})
How can I do something like that?
This is how it is done.
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface TestAnnotation {
TestAnnotationChild child();
// Or for an array
TestAnnotationChild[] children();
}
Usage
#TestAnnotation(
#TestAnnotationChild(
value = "42",
anotherValue = 42
)
)
However this part of your statement
and the values
does make me think you want to do something non-ordinary.
Could you clarify?
You should just use TestAnnotationChild value(); instead of Class<? extends TestAnnotationChild> annotation();.
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface TestAnnotation{
TestAnnotationChild value();
}
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface TestAnnotationChild {
// String or whatever Object you want
String[] value();
}
Now you can use the Annotations as you wanted:
#TestAnnotation(#TestAnnotationChild({"TEST"}))
you can just have a property of type TestAnnotationChild in your TestAnnotation, just like it was a string, or whatever else

Using enum as annotation

I have an enum :
public enum Vehicle {
CAR,
BUS,
BIKE,
}
I intend to use these enum values as annotations : #Vehicle.CAR, #Vehicle.BUS, #Vehicle.BIKE. Does java allow me to define them as annotations ?
No You can not do this. But if you want to use enum in annotation you can do like this
class Person {
#Presentable({
#Restriction(type = RestrictionType.LENGTH, value = 5),
#Restriction(type = RestrictionType.FRACTION_DIGIT, value = 2)
})
public String name;
}
enum RestrictionType {
NONE, LENGTH, FRACTION_DIGIT;
}
#Retention(RetentionPolicy.RUNTIME)
#interface Restriction {
//The below fixes the compile error by changing type from String to RestrictionType
RestrictionType type() default RestrictionType.NONE;
int value() default 0;
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
#interface Presentable {
Restriction[] value();
}
You can't use enum as annotations. But you can add the enum as an element of the annotation.
The enum
public enum Priority {
LOW,
MEDIUM,
HIGH
}
The annotation
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD})
public #interface TestAnnotation {
Priority priority() default Priority.MEDIUM;
}
The annotation usage
#TestAnnotation(priority = Priority.HIGH)
public void method() {
//Do something
}

Java Annotation "Inheritance"

I would like to generate tables from annotated objects. Right now I have the following schema in mind. I would like to annotate the object as follows:
#UI.App(
name = "locations",
columns = {
#UI.Presenter.PropertyColumn("title"),
#UI.Presenter.PropertyColumn("enabled"),
#UI.Presenter.StatusColumn,
#UI.Presenter.LastModifiedColumn
}
)
public class Location {
private String title;
private Boolean enabled;
}
For that I intended to use the following annotations
public interface UI {
#Retention(RetentionPolicy.RUNTIME) #Target({ElementType.TYPE})
public #interface App {
public String name();
public Presenter.Column[] columns() default {};
}
public interface Presenter {
#Retention(RetentionPolicy.RUNTIME) #Target({ElementType.TYPE})
public #interface Column {}
#Retention(RetentionPolicy.RUNTIME) #Target({ElementType.TYPE})
public #interface PropertyColumn {
public String value();
public boolean editable() default false;
}
#Retention(RetentionPolicy.RUNTIME) #Target({ElementType.TYPE})
public #interface StatusColumn {}
#Retention(RetentionPolicy.RUNTIME) #Target({ElementType.TYPE})
public #interface LastModifiedColumn {}
}
}
With annotation inheritance I would just let PropertyColumn, StatusColumn, and LastModifiedColumn to extend the Column interface. But there's no interface inheritance.
The main goal here is to have the overview annotation as concise as possible. What is the best way to achieve my goal?
This might be a case where annotations simply aren't flexible enough to represent complex structures. Although not as clean looking, I would consider using a single column annotation and creating enum constants for each column type like this:
#Retention(RetentionPolicy.RUNTIME) #Target({ElementType.TYPE})
public #interface Column {
ColumnType value();
String property() default "";
boolean editable() default false;
}
#UI.App(
name = "locations",
columns = {
#UI.Presenter.Column(value=ColumnType.PROPERTY, property="title"),
#UI.Presenter.Column(value=ColumnType.PROPERTY, property="enabled"),
#UI.Presenter.Column(ColumnType.STATUS),
#UI.Presenter.Column(ColumnType.LAST_MODIFIED)
}
)
Caveats are you need additional checking and documentation to prevent property and editable to be used with any column type. This approach won't work if you plan to add more column types with additional values, as it probably gets too complex then.

Annotations with optional attributes

I have an annotation like this:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
public #interface MyAnnotation {
String name();
Class<InstanceConverter> converter();
What I'm trying to do is make name required and converter optional. It appears that all attributes of an annotation are required by default. How do I make converter optional?
I've read through two articles on annotations and none seem to mention optional attributes.
Thanks.
You should add a default clause at the right side of the field declaration statement in the annotation #interface definition:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
public #interface MyAnnotation {
String name(); // mandatory
Class<InstanceConverter> converter() default InstanceConverter.class; // optional
}

Categories

Resources