Tem como fazer o parâmetro de um método ser de uma classe qualquer, mas que possua uma determinada anotação? Algo do tipo:
public void bla(Object.has(@AnotacaoX) objetoAnotado)
Tem como fazer o parâmetro de um método ser de uma classe qualquer, mas que possua uma determinada anotação? Algo do tipo:
public void bla(Object.has(@AnotacaoX) objetoAnotado)
Hum… você quer ver se, em tempo de execução, você recebeu um parâmetro anotado?
Você pode anotar parâmetros (veja http://java.sun.com/j2se/1.5.0/docs/api/java/lang/annotation/ElementType.html ), mas normalmente o que ocorre é que você analisa a classe à qual pertence o tal método que contém uma anotação no parâmetro, e você vê se está do jeito que você quer. Por exemplo, você poderia ter algo como:
interface Gambiarrable {
int doGambiarra (byte[] bytes);
}
@Retention (RetentionPolicy.RUNTIME)
@Target (ElementType.PARAMETER)
public @interface ReallyPOG {
string value();
}
class POG implements Gambiarrable {
public int doGambiarra (@ReallyPog (value="abc") byte[] bytes);
}
E quando você pegar um objeto de uma classe que implementa Gambiarrable (por exemplo), pode ver se o tal primeiro parâmetro do método tem uma anotação “ReallyPog”.
Acho que não dá para anotar uma chamada de método, como isto aqui (continuando meu exemplo):
doGambiarra (@ReallyPog ("xyz") new byte[] {1, 3, 4});
Thingol, desculpe mas de cara não consegui entender.
Não importaria a classe do parâmetro, a única coisa que importaria seria que a mesma tivesse uma anotação específica. Me parece uma informação disponível em compile time:
class A...
@AnotacaoX
class B...
class C {
public String fazAlgo(Object anotadoComAnotacaoX)...
a = new A();
b = new B();
c = new C();
c.fazAlgo(a); // o compilador vê que a.class não tem @AnotacaoX, não compila
c.fazAlgo(b); // compila
Dei uma acertada no meu exemplo, e realmente constatei que não posso incluir uma annotation em uma chamada de método.
import java.lang.annotation.*;
import java.lang.reflect.*;
interface Gambiarrable {
int doGambiarra (byte[] bytes);
}
@Retention (RetentionPolicy.RUNTIME)
@Target (ElementType.PARAMETER)
@interface ReallyPOG {
String value();
}
class POG implements Gambiarrable {
public int doGambiarra (@ReallyPOG (value="abc") byte[] bytes) {
return 0;
}
}
class FastPOG implements Gambiarrable {
public int doGambiarra (byte[] bytes) {
return 1;
}
}
class POGTester {
public static void printParameterAnnotations (Class<?> klass) {
System.out.println ("Classe " + klass.getName());
for (Method m : klass.getDeclaredMethods()) {
System.out.println (m.getName() + " => " );
Annotation[][] paramAnns = m.getParameterAnnotations();
for (int i = 0; i < paramAnns.length; ++i) {
System.out.print (" param " + i + " -> ");
Annotation[] anns = paramAnns[i];
for (Annotation ann : anns) {
System.out.print (ann.toString());
}
System.out.println();
}
}
}
public static void main(String[] args) {
Gambiarrable g = new FastPOG();
printParameterAnnotations (g.getClass());
g = new POG();
printParameterAnnotations (g.getClass());
// A seguinte sintaxe realmente não funciona:
// g.doGambiarra (@ReallyPOG (value="xyz") new byte[]{1, 2, 3});
}
}
Hum, agora entendi o que você quer. Você gostaria que o compilador checasse se determinado parâmetro foi anotado; se não tiver sido, então você gostaria de um erro de compilação.
Talvez você precise de um “Annotation Processor” (procure por apt na documentação do JDK.) Um “annotation processor” é uma forma de você modificar o comportamento do compilador para que ele, por exemplo, possa checar tais anotações.
Tem como fazer o parâmetro de um método ser de uma classe qualquer, mas que possua uma determinada anotação? Algo do tipo:public void bla(Object.has(@AnotacaoX) objetoAnotado)
Não. Mas pode fazer isto :
@ExpectAnnotation(AnotacaoX.class)
public void bla(Object objetoAnotado)
Depois vc pode usar o processador de anotações ou vc pode criar um proxy.
O proxy pode facilmente - via reflection - testar, em runtime se o objeto passado tem a sua classe anotada com a anotação esperada.
Hum, agora entendi o que você quer. Você gostaria que o compilador checasse se determinado parâmetro foi anotado; se não tiver sido, então você gostaria de um erro de compilação.Talvez você precise de um “Annotation Processor” (procure por apt na documentação do JDK.) Um “annotation processor” é uma forma de você modificar o comportamento do compilador para que ele, por exemplo, possa checar tais anotações.
Não o parâmetro, mas o tipo da variável.
Sei lá, acho engraçado ter tanta gambiarra e não ter isso. Acho até que seria simples, tipo:
public void umaGambiarraAMaisOutraAMenos(@AnotacaoX parametro)
Ou seja, você estaria dizendo que o tipo do parâmetro é uma subclasse de Object que possua a anotação @AnotacaoX (Object em si não tem é claro), o que pode ser verificado em tempo de compilação.
Não. Mas pode fazer isto :@ExpectAnnotation(AnotacaoX.class) public void bla(Object objetoAnotado)Depois vc pode usar o processador de anotações ou vc pode criar um proxy.
O proxy pode facilmente - via reflection - testar, em runtime se o objeto passado tem a sua classe anotada com a anotação esperada.
Eu quero justamente fugir da verificação em runtime. Como funciona o processador de anotações?
Uh, mas tem um pequeno problema aí.
Você está afirmando que gostaria que o parâmetro, em vez de pertencer a uma classe que deva IMPLEMENTAR uma determinada interface (ou uma interface que deva estender uma determinada interface), deva pertencer a uma classe ou interface e a classe ou interface é que deve estar anotada com determinada anotação.
Ou seja, o que se pode fazer é algo como:
@ReallyPOG (value="qwerty")
class BiggestPOG {
}
void processPoggableParameter (Object obj) {
if (obj.getClass().getAnnotation(ReallyPOG.class)) {
System.out.println ("OK, este parâmetro é realmente pogável");
} else {
System.out.println ("Puxa vida, já falei mil vezes que tem de passar um parâmetro pogado");
}
}
Sim thingol, mas isso aí é em runtime, btw eu uso Class.isAnnotationPresent…
Postei um bug na Sun…
interface Gambiarrable
Hahahahah, mais uma pro:
