2009-11-26 95 views
29

如何检索注释方法上的注释值?检索Java注释属性

我:

@myAnnotation(attribute1 = value1, attibute2 = value2) 
public void myMethod() 
{ 
    //I want to get value1 here 
} 
+0

你能提供更多关于你想要完成的细节吗? – Carl 2009-11-26 19:16:50

+0

正如我所说的,我想使用attribute1的值,而不必在代码 – 2009-11-26 19:21:17

+0

上重复它,这不是一个真正有效的编程方法。在注释中设置值与在代码内部设置最终变量或在方法外部的最终静态变量中设置值相比,没有任何优势。 – Jherico 2009-11-26 22:38:31

回答

43
  1. 获取Method实例。
  2. 获取注释。
  3. 获取注释属性值。

喜欢的东西:

Method m = getClass().getMethod("myMethod"); 
MyAnnotation a = m.getAnnotation(MyAnnotation.class); 
MyValueType value1 = a.attribute1(); 

你需要赶上/处理适当的例外,当然。上述假定您确实是从当前类检索方法(更换getClass()Class.forName()),还可以在问题的方法是公共的(使用getDeclaredMethods()如果不是这种情况)

+0

不应该是“MyValueType value1 = a.getAttribute1();” – 2009-11-26 19:27:15

+0

或更多像“a.attribute()' – Bozho 2009-11-26 19:35:35

+0

当然应该有。谢谢,编辑 – ChssPly76 2009-11-26 19:40:03

19

两个重要的事情:

  • 有是无法获得当前方法,例如没有getMethod(),如getClass()。因此,访问自己注释的方法需要知道自己的名字。
  • 注释的保留策略必须设置为RUNTIME,因此您可以在运行时访问注释。缺省值是编译时,这意味着类文件中的注释可用,但不能在运行时使用反射来访问。

完整的示例:

@Retention(RetentionPolicy.RUNTIME) 
public static @interface MyAnnotation { 
    String value1(); 

    int value2(); 
} 

@Test 
@MyAnnotation(value1 = "Foo", value2 = 1337) 
public void testAnnotation() throws Exception { 
    Method[] methods = getClass().getMethods(); 
    Method method = methods[0]; 
    assertEquals("testAnnotation", method.getName()); 
    MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); 
    assertEquals("Foo", annotation.value1()); 
    assertEquals(1337, annotation.value2()); 
} 
+4

有一种方法可以获得当前的方法,可以是'Thread.currentThread()。getStackTrace() [2] .getMethodName()'或'new Throwable()。fillInStackTrace()。getStackTrace()[0]。getMethodName()'应该这样做。 – ChssPly76 2009-11-26 19:48:23

+1

+1提醒保留 – basszero 2009-11-26 19:53:24

+1

@ ChssPly76,构建堆栈跟踪并不完全可靠,因为javadoc提到:“某些虚拟机在某些情况下可能会忽略堆栈跟踪中的一个或多个堆栈帧,在极端情况下,一个没有堆栈跟踪信息的虚拟机被允许从这个方法返回一个零长度的数组。 – gustafc 2009-11-27 07:21:03

1

@mhaller:太长了一点对您帖子的注释。显然还需要进一步完善,以应对重载方法,但也不是不可能:

import java.lang.reflect.Method; 

public class Hack { 
    public static void main (String[] args) { 
     (new Hack()).foobar(); 
    } 
    public void foobar() { 
     Method here = getCurrentMethod(this); 
     System.out.format("And here we are: %s\n", here); 
    } 
    public static final Method getCurrentMethod(Object o) { 
     String s = Thread.currentThread().getStackTrace()[2].getMethodName(); 
     Method cm = null; 
     for(Method m : o.getClass().getMethods()){ 
      if(m.getName().equals(s)){ 
       cm = m; break; 
      } 
     } 
     return cm; 
    } 
} 

[编辑:信用卡/感谢亚历山大Priymak为察觉在main()错误]

+3

我有一种感觉,如果你真的在生产代码中做到这一点,它会召唤大老头去吞噬你的灵魂! – 2009-11-26 21:14:14

+0

@Skip Head - 为什么?这里需要注意两点 - (1)理论上的数组索引**在某些JVM上可能不同于2,但通过遍历整个跟踪很容易解决; (2)这不适用于重载的方法;你可以用javassist做一些黑魔法来根据行号猜测正确的那个,但这真的有点不确定。除此之外,它的工作原理是完美的 - 你如何看待栈跟踪工作? – ChssPly76 2009-11-26 21:26:20

+0

@ ChssPly76:无需走完整个痕迹。跟踪方法从顶部开始,直到找到它自己。而来电是下一个。 – alphazero 2009-11-26 22:26:13

0

要获得目前的方法,请尝试使用此代码:

Thread.currentThread().getStackTrace()[1].getClassName().toString()+\".\"+Thread.currentThread().getStackTrace()[1].getMethodName().toString()