Java 如何以重构安全的方式分配方法名(或注释元素)字符串?

Java 如何以重构安全的方式分配方法名(或注释元素)字符串?,java,reflection,annotations,refactoring,Java,Reflection,Annotations,Refactoring,假设我有一个类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

假设我有一个类
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));
    // ...
}
不确定这是否有可能,是否有任何方法可以解决


现在真正的问题来了——即使您可以像上面那样进行分类,我尝试访问的真正问题是注释属性/元素名称。但是注释是抽象的,甚至不能实例化。这可能吗?

注释只是一个接口,您也可以将其子类化:)例如,注释

public @interface SomeAnno
{
    String attr1();
    int    attr2();
}
您需要一种“静态类型”的方式来引用名称“attr1”、“attr2”

这可以通过一些方法中精心策划的阴谋来实现

String n1 = name( SomeAnno::attr1 );

class MyAnno implements SomeAnno
{
    String attr1(){ ... }
MyAnno.attr1()/attr2()/…
每一种都会引发不同的副作用<代码>名称(操作)比较
操作的副作用,并将其与一个属性匹配


我们可以将这个技巧推广到编写一个通用的util,它可以在任何注释类型(实际上是任何接口类型)上工作



但这真的不值得:)您只需硬编码名称,并执行运行时检查(尽早)以断言名称确实有效

注释只是一个接口,您也可以将其子类化!:)例如,注释

public @interface SomeAnno
{
    String attr1();
    int    attr2();
}
您需要一种“静态类型”的方式来引用名称“attr1”、“attr2”

这可以通过一些方法中精心策划的阴谋来实现

String n1 = name( SomeAnno::attr1 );

class MyAnno implements SomeAnno
{
    String attr1(){ ... }
MyAnno.attr1()/attr2()/…
每一种都会引发不同的副作用<代码>名称(操作)
比较
操作的副作用,并将其与一个属性匹配


我们可以将这个技巧推广到编写一个通用的util,它可以在任何注释类型(实际上是任何接口类型)上工作



但这真的不值得:)您只需硬编码名称,并执行运行时检查(尽早)以断言名称确实有效

如果您使用的是eclipse:它也可以替换对该类的非代码引用(只要您使用的是完全限定名)。None code表示字符串、注释或任何其他文件的内容。只有通过反射调用
Foo
方法时,这才重要。否则,如果您在
Foo
中有常规的方法调用,它们将通过IDE的“更改方法签名”功能进行重构,或者如果您手动更改方法签名,它们将不会编译。不,没有编译时静态方式按名称引用方法。您能详细说明“真正的问题”吗?如果您想绝对确保旧代码仍然有效,请创建一个新类,复制所有方法,使旧类充满委派。如果您使用eclipse:它也可以替换对该类的非代码引用(只要您使用完全限定的名称)。None code表示字符串、注释或任何其他文件的内容。只有通过反射调用
Foo
方法时,这才重要。否则,如果您在
Foo
中有常规的方法调用,它们将通过IDE的“更改方法签名”功能进行重构,或者如果您手动更改方法签名,它们将不会编译。不,没有编译时静态方式按名称引用方法。您能详细说明“真正的问题”吗?如果你想绝对确保旧代码仍然有效,那么创建一个新类,复制所有方法,让旧类充满委托人我仍然不太明白。如果
name
比较了这些操作的副作用并与之匹配,那么它会返回什么?我看不出有任何方法可以绕过它返回字符串文本,这将完全挫败执行此操作的目标。我们知道调用了什么方法,但不知道它的(重构安全)名称。顺便说一下,我使用的是Java7,所以我也不能使用lambdas;)我还是不太明白。如果
name
比较了这些操作的副作用并与之匹配,那么它会返回什么?我看不出有任何方法可以绕过它返回字符串文本,这将完全挫败执行此操作的目标。我们知道调用了什么方法,但不知道它的(重构安全)名称。顺便说一下,我使用的是Java7,所以我也不能使用lambdas;)