Java 方法注释和默认访问级别上的奇怪行为
这是我的问题 我在包pkg3中有一个注释:Java 方法注释和默认访问级别上的奇怪行为,java,reflection,annotations,Java,Reflection,Annotations,这是我的问题 我在包pkg3中有一个注释: package pkg3; import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface TestAnno { } 另外,我在pkg1包中有两个类,一个具有公共访问权限,另一个具有默认访问权限 package pkg1; import pkg3.TestAnno; class C
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() { }
}
及
最后,我在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");
}
}
}
}
运行这个示例时,我希望看到这样的信息:两个方法都没有@testnno-present-test1和test3,但我只看到一个test3,而且。。。奇怪的是,test1和test2方法是在类2中声明的
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中获取带注释的公共方法?这个答案只是一个人在凌晨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()
方法,但方式不同
如果您查看javapsomedefaultclass.class的结果,您将看到
class SomeDefaultClass extends SomeClass {
SomeDefaultClass();
}
因此,它的二进制文件中没有test()
方法,因此它将从SomeClass
使用它,该类具有TestAnno
注释
另一方面,如果查看javapsomepublicclass
的结果,您将看到
public class SomePublicClass extends SomeClass {
public SomePublicClass();
public void test();
}
这意味着test()
方法的代码已在SomePublicClass
中被重写,因此此方法已在SomePublicClass
中再次声明,但不幸的是,没有以前的注释,并且由于被重写的方法没有注释,您将无法在代码中看到它们。(为什么在编译器重写方法时不添加注释?老实说,我不知道:/)
为什么会发生超越?我怀疑由于SomePublicClass
是public并且test
也是public它应该可以从所有包中访问,但是由于SomeClass
具有默认/package可见性,这个方法不能通过SomeClass
从其包外部访问
为了防止将test
方法从一个类移动/复制到另一个类,您可以将两个类都设置为public
或default/package
这是官方行为,但这是一种奇怪的策略。
public class SomePublicClass extends SomeClass {
public SomePublicClass();
public void test();
}