Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using arrays in a custom annotation [duplicate]

I have a class that defines a bunch of things, i.e., target names and arrays of parameters:

public class Actions {

    protected static final String A_TARGET = "do_a";
    protected static final String[] A_ARGS = { "paramA", "paramB" };

    ...
}

I am trying to write a custom annotation to avoid action registration in a constructor, so I have defined:

public @interface MyAnno{

    String actionTarget();
    String[] actionArgs();
}

And am trying to use it as such:

@MyAnno(
    actionTarget = Actions.A_TARGET,
    actionArgs = Actions.A_ARGS   <-- compile error
)
public void doA() {
}

I am however experiencing an issue with the marked line, an issue with passing in the String array of arguments to the annotation:

The value for annotation attribute MyAnno.A_ARGS must be an array initializer

If I replace Actions.A_ARGS with the array I have defined in my Actions class, { "paramA", "paramB" }, the error goes away...

My question is:

How can I go about having this args array defined elsewhere, and then using it in the Annotation?

like image 387
Matt Clark Avatar asked Oct 17 '25 05:10

Matt Clark


2 Answers

This is not doable in Java.

See this SO question for details: How to supply value to an annotation from a Constant java

The best you can get is to define the individual array items as constants and reuse them, i.e.

public class Actions {

    protected static final String A_TARGET = "do_a";

    protected static final String PARAM_A = "paramA";
    protected static final String PARAM_B = "paramB";
    protected static final String[] A_ARGS = { PARAM_A, PARAM_B };

    ...
}

And then

@MyAnno(
    actionTarget = Actions.A_TARGET,
    actionArgs = {Actions.PARAM_A, Actions.PARAM_B}
)
public void doA() {
}

This will help to avoid "string duplication" and typo errors, but won't resolve the duplication of the combinations.

like image 188
Alex Shesterov Avatar answered Oct 18 '25 19:10

Alex Shesterov


You cannot use static array field value as a value for annotation, because it is not a constant expression.

Consider following example:

@Target(ElementType.METHOD)
public @interface MyAnno {
    String[] arrayParam();
    String stringParam();
}

public static final String[] arrayConstant = {"x", "y"};
public static final String stringConstant = "z";

static {
    stringConstant = "t"; // error, final string cannot be changed
    arrayConstant[0] = "t"; // valid (thus array is not constant)
}

@MyAnno(
        arrayParam = arrayConstant, // error, array is not a constant
        stringParam = stringConstant // valid, static final string field is a constant
) 
void myMethod() {

}

Static final String fields are proper constant expressions as they cannot be changed in runtime, so compiler marks them as constant.

Static final array fields always can be changed in runtime, so compliler cannot mark it as a constant.

like image 42
Kostiantyn Avatar answered Oct 18 '25 18:10

Kostiantyn



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!