Java 受保护的访问修饰符允许在非派生情况下访问字段
我在包Java 受保护的访问修饰符允许在非派生情况下访问字段,java,Java,我在包bbb中有类c1: package bbb; public class c1 { protected static int a = 5; } 我必须创建导入c1的类: package aaa; import bbb.c1; public class c2 extends c1 { public c2() { a = 10; c1 c = new c1();
bbb
中有类c1
:
package bbb;
public class c1 {
protected static int a = 5;
}
我必须创建导入c1
的类:
package aaa;
import bbb.c1;
public class c2 extends c1 {
public c2() {
a = 10;
c1 c = new c1();
c.a = 60;
}
}
package aaa;
import bbb.c1;
public class c4 {
public c4() {
c1 c = new c1();
c.a = 60;
}
}
c2
和c4
都使用c1
c2
源于c1
,而c4
则不是。我对这两个类中的变量c
感兴趣。在类c4
的情况下,我有编译错误“a在bbb.c1中有受保护的访问”
,而在c2
情况下c
变量工作正常
我希望派生类可以使用内部字段a
,但不允许在新创建的c
变量中使用它,就像在c4
案例中一样,因为它不是通过派生访问字段。逻辑在哪里
UPD
Mala Gupta“OCA Java SE 8程序员I认证指南”一书的参考资料告诉我们,派生类对象只能通过继承而不是引用来访问受保护的方法:
默认访问权限可与包专用(可访问)进行比较
仅在包内),并且受保护的访问可以与包进行比较-
private+kids(“kids”指派生类)。儿童可以访问受保护的
方法只能通过继承而不能通过引用(通过
在对象上使用点运算符)
这是错误吗
public class c4 {
public c4() {
c1 c = new c1();
c.a = 60;
}
}
类c1
是public
,因此另一个包中的c4
可以访问它。但是,变量c1.a
受保护
,这意味着它仅对包bbb
或c1
的任何子项可见。因此,c.a=60代码>是CompileTimeError
,因为c1.a
在bbb
包中不可见,并且c4
不扩展c1
也许对你有用
______________________________________________________________
| │ Class │ Package │ Subclass │ Subclass │ World |
| │ │ │(same pkg)│(diff pkg)│ |
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|public │ + │ + │ + │ + │ + |
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|protected │ + │ + │ + │ + │ |
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|no modifier│ + │ + │ + │ │ |
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|private │ + │ │ │ │ |
|___________|_______|_________|__________|__________|________|
+ : accessible blank : not accessible
______________________________________________________________
| │ 等级│ 包裹│ 子类│ 子类│ 世界|
| │ │ │(同一包装)│(不同包装)│ |
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|公开的│ + │ + │ + │ + │ + |
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|保护│ + │ + │ + │ + │ |
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|无修饰语│ + │ + │ + │ │ |
|───────────┼───────┼─────────┼──────────┼──────────┼────────|
|私人的│ + │ │ │ │ |
|___________|_______|_________|__________|__________|________|
+:可访问空白:不可访问
我认为这是人们常见的误解。如果一个类可以访问它自己的属性(比如c1.a,在你的例子中),那么它可以在同一个类的另一个实例中访问同一个属性,而不管它的访问修饰符是什么(甚至是私有的)。例如,这是有效的:
class Base {
private int x = 0;
public void method(Base other) {
other.x += 5;
}
}
如果你想知道为什么,我想这就是它的设计初衷。我想象其他支持面向对象设计的语言也会这样工作(我知道它在C++中是这样的)
注意:这与您的问题无关,但使用大写起始词(此处为C1、C2、C4)命名类是一种很好的惯例,这样代码更容易被其他人阅读。在C2
构造函数中允许访问受保护字段a
,因为C2
是C1
的子类。从
如果通过限定名称Q.Id进行访问,其中Q是
ExpressionName,则仅当类型为
表达式Q的子类是S或S的子类