Is it possible to change the value of a note at run time?

7

Considering the following annotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MinhaAnotacao {
   String valor();
}

Defined in a class:

@MinhaAnotacao(valor = "algum valor")
class ExemploStackOverflow {
}

I know you can get the value of the valor field at runtime, OK. But is it possible to change this value too? For example:

ExemploStackOverflow exemplo = new ExemploStackOverflow();

// Exibe "algum valor"
System.out.println(exemplo.getClass().getAnnotation(MinhaAnotacao.class).valor());

// Chama algum método que altera o conteúdo do campo "valor" da anotação.
AnnotacoesUtils.mudarValor(exemplo, "novo valor");

// Exibiria "novo valor"
System.out.println(exemplo.getClass().getAnnotation(MinhaAnotacao.class).valor());

Is there any way to do this?

I found a possible solution in StackOverflow that seems to be gambiarra. But it does not work in Java version 8, an exception is thrown when calling:

Field field = Class.class.getDeclaredField("annotations");
    
asked by anonymous 26.05.2016 / 04:23

2 answers

1

You can not change the annotation itself, but if an annotation field is a class, you can change its static fields.

Note:

package teste.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;    

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Anota {

    Class<? extends AnotaValue> value();
}

Class that will be the value of Annotation:

package teste.annotation;

public class AnotaValue {

    public static String valor = "velho";
}

Example usage:

package teste.annotation;

import java.lang.reflect.Field;
import java.util.logging.Logger;

@Anota(AnotaValue.class)
public class Exemplo {

Field getCampoAnotado() throws NoSuchFieldException {
    Anota annotation = this.getClass().getAnnotation(Anota.class);
    return annotation.value().getDeclaredField("valor");
}

String getValorDoCampoAnotado() throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    return (String) getCampoAnotado().get(null);
}

void setValorDoCampoAnotado(String valor) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    getCampoAnotado().set(null, valor);
}

public static void main(String[] args) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    Exemplo exemplo = new Exemplo();
    Logger.getLogger(Exemplo.class.getName()).info(exemplo.getValorDoCampoAnotado());
    exemplo.setValorDoCampoAnotado("novo");
    Logger.getLogger(Exemplo.class.getName()).info(exemplo.getValorDoCampoAnotado());
}
}
    
17.01.2018 / 01:33
0

I do not think so. The annotations are transformed into compile-time statements and the values become constant. You can even hack to display the value you want, but this does not change the annotation itself, only what is shown. So, as Fagner-Fonseca said, it is not good practice.

    
15.04.2017 / 18:36