为什么包保护方法在同一个包中不可见?
Why is package-protected method not visible in the same package?
假设我们有两个包 p1
和 p2
和 classes p1.M1
由 p2.M12
扩展如下:
package p1;
public class M1 {
void method1() {
System.out.println("Method 1 called");
}
}
package p2;
import p1.M1;
public class M12 extends M1 {
void method2() {
System.out.println("Method 2 called");
}
}
让我们用 p2.B
扩展 M12
:
package p2;
public class B extends M12 {
public void doSomething() {
method1();
method2();
}
}
这会产生编译错误,因为 method1
,在 p1
中受包保护在 p2
中不可见。 method2
可见,没有问题。
现在让我们用 p1.A
扩展 p2.M12
:
package p1;
import p2.M12;
public class A extends M12 {
public void doSomething() {
method1();
method2();
}
}
method2()
(这是可以理解的)和method1()
的编译错误:
我的问题是:为什么在包 p1
中受包保护的 method1
在同一包 class A
中不可见 p1
?
可见性必须流经 class 层次结构。
class 层次结构是 A --> M12 --> M1
由于 M1.method1
对 M12
不可见,因此它的任何子 class 也不可见,例如 A
.
我认为理解这种行为的最简单方法是 "A is a M12"
当你声明继承时,你告诉A从M12获取它的行为,但是M12没有可见的方法method1。
我们来做个有趣的实验:
public class M12 extends p1.M1 {
public void method1() {
System.out.println("Method 1 called");
}
void method2() {
System.out.println("Method 2 called");
}
}
忘记 A.. 当您声明这样的方法时,它是允许的 - 如果您没有 @Override。
但是,如果 M1 是:
public class M1 {
public void method1() {
System.out.println("Method 1 called");
}
}
你可以:
public class M12 extends p1.M1 {
@Override
public void method1() {
System.out.println("Method 1 called");
}
void method2() {
System.out.println("Method 2 called");
}
}
现在,回到 M1 和 M2 的原始代码,重新声明方法并创建方法一 public:
public class M12 extends p1.M1 {
public void method1() {
System.out.println("Method 1 called");
}
public void method2() {
System.out.println("Method 2 called");
}
}
那么,您就可以
public class A extends M12 {
public void doSomething() {
method1();
method2();
}
}
好吧,这是一个微不足道的案例,但要完成序列就缺少了……
最重要的是,从语义上讲,您可以通过 IS 关系来解释。
如果需要更多(https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html):
以下table显示了每个修饰符允许的成员访问权限。
访问级别
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N
首先,什么是class的成员? Java Language Specification 状态
A class body may contain declarations of members of the class, that
is, fields (§8.3), methods (§8.4), classes (§8.5), and interfaces
(§8.5).
它们是由什么组成的? JLS states
The members of a class type are all of the following:
- Members inherited from its direct superclass (§8.1.4), except in class Object, which has no direct superclass
- Members inherited from any direct superinterfaces (§8.1.5)
- Members declared in the body of the class (§8.1.6)
它还提到
Only members of a class that are declared protected
or public
are
inherited by subclasses declared in a package other than the one in
which the class is declared.
所有这些都在 chapter on Inheritance
中改写了
A class C
inherits from its direct superclass all concrete methods m
(both static and instance) of the superclass for which all of the
following are true:
m
is a member of the direct superclass of C
.
m
is public
, protected
, or declared with package access in the same package as C`.
- No method declared in
C
has a signature that is a subsignature (§8.4.2) of the signature of m
.
classM1
的成员是method1
(以及Object
的所有方法)。 M12
,与它的直接超级 class、M1
在不同的包中,不继承 method1
。因此 M12
的成员只有 method2
.
B
的直接superclass是M12
,在同一个包里。因此它继承了它的成员 method2
。 B
对 method1
一无所知。如果您使用 javac
编译代码,则会收到 cannot find symbol
编译错误。 (似乎 Eclipse 正在尝试猜测您要做什么。)
同样,A
的直接superclass是M12
,只是在不同的包中。出于这个原因,它不会继承 method2
。 A
对 method1
或 method2
一无所知,因为它没有继承它们。找不到这两个符号。
假设我们有两个包 p1
和 p2
和 classes p1.M1
由 p2.M12
扩展如下:
package p1;
public class M1 {
void method1() {
System.out.println("Method 1 called");
}
}
package p2;
import p1.M1;
public class M12 extends M1 {
void method2() {
System.out.println("Method 2 called");
}
}
让我们用 p2.B
扩展 M12
:
package p2;
public class B extends M12 {
public void doSomething() {
method1();
method2();
}
}
这会产生编译错误,因为 method1
,在 p1
中受包保护在 p2
中不可见。 method2
可见,没有问题。
现在让我们用 p1.A
扩展 p2.M12
:
package p1;
import p2.M12;
public class A extends M12 {
public void doSomething() {
method1();
method2();
}
}
method2()
(这是可以理解的)和method1()
的编译错误:
我的问题是:为什么在包 p1
中受包保护的 method1
在同一包 class A
中不可见 p1
?
可见性必须流经 class 层次结构。
class 层次结构是 A --> M12 --> M1
由于 M1.method1
对 M12
不可见,因此它的任何子 class 也不可见,例如 A
.
我认为理解这种行为的最简单方法是 "A is a M12"
当你声明继承时,你告诉A从M12获取它的行为,但是M12没有可见的方法method1。
我们来做个有趣的实验:
public class M12 extends p1.M1 {
public void method1() {
System.out.println("Method 1 called");
}
void method2() {
System.out.println("Method 2 called");
}
}
忘记 A.. 当您声明这样的方法时,它是允许的 - 如果您没有 @Override。 但是,如果 M1 是:
public class M1 {
public void method1() {
System.out.println("Method 1 called");
}
}
你可以:
public class M12 extends p1.M1 {
@Override
public void method1() {
System.out.println("Method 1 called");
}
void method2() {
System.out.println("Method 2 called");
}
}
现在,回到 M1 和 M2 的原始代码,重新声明方法并创建方法一 public:
public class M12 extends p1.M1 {
public void method1() {
System.out.println("Method 1 called");
}
public void method2() {
System.out.println("Method 2 called");
}
}
那么,您就可以
public class A extends M12 {
public void doSomething() {
method1();
method2();
}
}
好吧,这是一个微不足道的案例,但要完成序列就缺少了…… 最重要的是,从语义上讲,您可以通过 IS 关系来解释。
如果需要更多(https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html):
以下table显示了每个修饰符允许的成员访问权限。
访问级别
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N
首先,什么是class的成员? Java Language Specification 状态
A class body may contain declarations of members of the class, that is, fields (§8.3), methods (§8.4), classes (§8.5), and interfaces (§8.5).
它们是由什么组成的? JLS states
The members of a class type are all of the following:
- Members inherited from its direct superclass (§8.1.4), except in class Object, which has no direct superclass
- Members inherited from any direct superinterfaces (§8.1.5)
- Members declared in the body of the class (§8.1.6)
它还提到
Only members of a class that are declared
protected
orpublic
are inherited by subclasses declared in a package other than the one in which the class is declared.
所有这些都在 chapter on Inheritance
中改写了A class
C
inherits from its direct superclass all concrete methodsm
(both static and instance) of the superclass for which all of the following are true:
m
is a member of the direct superclass ofC
.m
ispublic
,protected
, or declared with package access in the same package as C`.- No method declared in
C
has a signature that is a subsignature (§8.4.2) of the signature ofm
.
classM1
的成员是method1
(以及Object
的所有方法)。 M12
,与它的直接超级 class、M1
在不同的包中,不继承 method1
。因此 M12
的成员只有 method2
.
B
的直接superclass是M12
,在同一个包里。因此它继承了它的成员 method2
。 B
对 method1
一无所知。如果您使用 javac
编译代码,则会收到 cannot find symbol
编译错误。 (似乎 Eclipse 正在尝试猜测您要做什么。)
同样,A
的直接superclass是M12
,只是在不同的包中。出于这个原因,它不会继承 method2
。 A
对 method1
或 method2
一无所知,因为它没有继承它们。找不到这两个符号。