Is it possible to change the value of an annotation at runtime?

Asked

Viewed 534 times

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 it is possible to get the value of the field valor at runtime, OK. But is it possible to change this value as well? 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 no Stackoverflow that seems to be gambiarra. But it does not work in version 8 of Java, is released an exception when calling:

Field field = Class.class.getDeclaredField("annotations");
  • 3

    What you’re trying to do is not good practice. I found this link that can help you: http://stackoverflow.com/questions/32089290/change-annotation-value-of-field-annotation-in-java-8

2 answers

1

Cannot change the annotation itself, but if an annotation field is a class, it is possible to change its static fields.

Annotation:

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 Annotation value:

package teste.annotation;

public class AnotaValue {

    public static String valor = "velho";
}

Example of use:

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());
}
}

0

I don’t think so. Annotations are transformed into instructions at compile time and values become constant. You can even hack it to present the value you want, but that doesn’t change the annotation itself, just what is shown. So, as @Fagner-Fonseca said, it’s not good practice.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.