gpt4 book ai didi

java - 方法注释和默认访问级别的奇怪行为

转载 作者:行者123 更新时间:2023-12-02 07:49:01 27 4
gpt4 key购买 nike

这是我的问题...

我在包 pkg3 中有一个注释:

package pkg3;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TestAnno {

}

此外,我在包 pkg1 中有两个类,一个具有公共(public)访问权限,一个具有默认访问权限

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 仅返回给定玻璃中的公共(public)方法(并且都是父类(super class)),但是......这对我来说很奇怪。

我使用它是为了将生成的类(具有默认访问权限)与实现类(它们是公共(public)的,并且它们正在扩展生成的类)分开。我是否要在生成的类中使用公共(public)访问(我希望它们对世界其他地方不可见),或者有什么方法可以从 Class1 获取带注释的公共(public)方法?

最佳答案

这个答案只是一个人在凌晨 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()

如您所见,使用 package 修饰符扩展类的公共(public)类不会继承注释,但使用 package 修饰符的类会继承注释。

<小时/>

这是为什么?
SomeDefaultClassSomePublicClass 都“继承”了 test() 方法,但方式不同。

如果您查看 javap SomeDefaultClass.class 的结果,您会看到

class SomeDefaultClass extends SomeClass {
SomeDefaultClass();
}

因此它的二进制文件中没有 test() 方法,因此它将使用具有 TestAnno 注释的 SomeClass 方法。

另一方面,如果您查看 javap SomePublicClass 的结果,您将看到

public class SomePublicClass extends SomeClass {
public SomePublicClass();
public void test();
}

这意味着 test() 方法的代码已在 SomePublicClass 中被重写,因此该方法已在 SomePublicClass 中再次声明,但是 不幸的是没有以前的注释并且由于重写的方法没有注释,因此您不会在代码中看到它们。 (为什么编译器重写方法时不添加注释?老实说,我不知道:/)

为什么会发生覆盖?我怀疑,因为 SomePublicClasspublic 并且 test 也是 public 它应该可以从所有包访问,但由于 SomeClass 具有 default/package 可见性,因此无法通过 SomeClass 访问此方法从其包装外部。

<小时/>

为了防止将 test 方法从一个类移动/复制到另一个类,您可以将这两个类设置为 publicdefault/package

关于java - 方法注释和默认访问级别的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17624453/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com