假设我有一个班级com.example.Foo
,另一个班级com.sample.Bar
需要知道Foo
的完全限定名称。如果我是Java新手,我可能会说:
public class Bar {
private String fooName = "com.example.Foo";
//...
}
但是,如果我重构Foo
来更改名称或包,则更改不会反映在Bar
中,除非IDE非常聪明。所以做这样的事情会更好:
import com.example.Foo;
public class Bar {
private String fooName = Foo.class.getName();
// ...
}
这样,如果我重构Foo
,则应该Bar
选择更改。
现在考虑方法。如果我在类Foo
中有一个方法名称并且Bar
需要知道该名称,那么我能做的最好就是:
public class Bar {
private String bazName = Foo.class.getMethod("bazMethod", Qux.class);
// ...
}
但我实际上没有取得任何成果 - 我仍然有一个字符串文字“bazMethod”,如果真正的bazMethod
被重命名,它将不会被重构。
我真正想要的是:
public class Bar {
private String bazName = tellMeTheMethodName((new Foo()).bazMethod(null));
// ...
}
不确定这是否可行以及是否有任何解决办法。
现在出现了真正的问题 - 即使您可以按上述方式对其进行排序,我尝试访问的真实内容是注释属性/元素名称。但注释是抽象的,甚至无法实例化。这可能吗?
答案 0 :(得分:0)
Annotation只是一个接口,您也可以将其子类化! :)例如,注释
public @interface SomeAnno
{
String attr1();
int attr2();
}
你想要一个"静态输入"引用名称的方式" attr1"," attr2"。
这可以通过一些方法中的一些精心设计的阴谋来实现。
String n1 = name( SomeAnno::attr1 );
class MyAnno implements SomeAnno
{
String attr1(){ ... }
MyAnno.attr1()/attr2()/...
每个都会引发明显的副作用; name(action)
比较action
的副作用,并将其与attr之一进行匹配。
我们可以概括这个技巧来编写一个适用于任何注释类型的通用工具(实际上,任何接口类型)。
SomeAnno anno = proxy(SomeAnno.class);
String n1 = name( anno::attr1 );
但这真的不值得:)你可以只对该名称进行硬编码,并进行运行时检查(尽早)以断言该名称确实有效。