这是我的问题......
我在包pkg3中有一个注释:
package pkg3;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TestAnno {
}
此外,我在包pkg1中有两个类,一个具有公共访问权限,另一个具有默认访问权限
package pkg1;
import pkg3.TestAnno;
class Class1 {
@TestAnno
public void test1() { }
public void test2() { }
}
和
package pkg1;
import pkg3.TestAnno;
public class Class2 extends Class1 {
@TestAnno
public void test3() { }
public void test4() { }
}
最后我在包pkg2
中有一个主类package pkg2;
import java.lang.reflect.Method;
import pkg1.Class2;
import pkg3.TestAnno;
public class MainClass {
public static void main(String[] args) {
Class2 cls = new Class2();
for(Method m: cls.getClass().getMethods()) {
System.out.println(m);
if (m.getAnnotation(TestAnno.class) != null) {
System.out.println(" > hass anno");
}
}
}
}
运行这个例子我希望看到信息,两个方法都有@TestAnno存在 - test1和test3,但我只看到一个test3,而且...奇怪的是,方法test1和test2被列为原样在Class2类中声明。
public void pkg1.Class2.test3()
> hass anno
public void pkg1.Class2.test4()
public void pkg1.Class2.test1()
public void pkg1.Class2.test2()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
... rest methods from java.lang.Object
我知道,getMethods只返回给定glass的公共方法(并且它是所有超类)但是......这对我来说很奇怪。
我正在使用它来从实现类(它们是公共的并且它们扩展生成的类)中分离生成的类(具有默认访问权限)。 我是否要在生成的类中使用公共访问(我希望它们不会被世界其他地方看到)或者有没有办法从Class1获取带注释的公共方法?
答案 0 :(得分:0)
这个答案只是一个男人在凌晨3点做出的“一大概率”,所以它需要JLS对抗,更好的术语和更多的信息。我打算将其作为评论发布,但不幸的是它太长了:/
让我们来看看这个类
class SomeClass {
@TestAnno
public void test(){}
}
class SomeDefaultClass extends SomeClass {
}
public class SomePublicClass extends SomeClass {
}
现在看看这段代码及其结果
Method m1 = SomePublicClass.class.getMethod("test");
Method m2 = SomeDefaultClass.class.getMethod("test");
System.out.println(m1 + "\t> " + m1.getAnnotation(TestAnno.class));
System.out.println(m2 + "\t\t> " + m2.getAnnotation(TestAnno.class));
输出
public void SomePublicClass.test() > null
public void SomeClass.test() > @TestAnno()
如您所见,使用包修饰符扩展类的公共类不会继承注释,但包含修饰符的类会继承注释。
为什么?
SomeDefaultClass
和SomePublicClass
“都继承了”test()
方法,但不是以同样的方式。
如果您查看javap SomeDefaultClass.class
的结果,您会看到
class SomeDefaultClass extends SomeClass {
SomeDefaultClass();
}
因此它的二进制文件中没有test()
方法,因此它将使用SomeClass
中有TestAnno
注释的方法。
另一方面,如果您查看javap SomePublicClass
的结果,您会看到
public class SomePublicClass extends SomeClass {
public SomePublicClass();
public void test();
}
这意味着test()
方法的代码已在SomePublicClass
中被覆盖,因此此方法已在SomePublicClass
中再次声明,但 在以前没有注释 > 并且由于重写方法没有注释,因此您不会在代码中看到它们。 (为什么在编译器重写方法时不添加注释?老实说,我不知道:/)
为什么压倒一切?我怀疑,因为SomePublicClass
公开 而test
也是 公开 ,所以可以从所有包中访问,但由于SomeClass
具有默认/包可见性,因此无法通过SomeClass
从其包外部访问此方法。
为防止将test
方法从一个类移动/复制到另一个类,您可以同时创建public
或default/package
个类。