受保护的访问修饰符允许访问非派生大小写的字段



我在包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;
}
}

c2c4都使用c1c2源自c1,而c4- 不是。我对这两个类中的变量c感兴趣。在类c4的情况下,我有编译错误"a has protected access in bbb.c1"c2而在情况下c变量工作正常。

我预计派生类可能会使用内部字段a,但不应该允许在新创建的c变量中使用它,就像它在这种情况下所做的那样c4因为它不是通过派生访问字段。逻辑在哪里?

UPD

书籍Mala Gupta "OCA Java SE 8 Programmer I Certification Guide"有引用,它告诉派生类对象只能通过继承而不是引用来访问受保护的方法:

默认访问可以与包私有(可访问(进行比较 仅在包内(,并且受保护的访问可以与包进行比较 私有 + 孩子("孩子"是指派生类(。孩子们可以访问受保护的 方法仅通过继承而不是通过引用(通过以下方式访问成员 在对象上使用点运算符(

这是错误的吗?

构造函数中允许访问受保护字段ac2因为c2c1的子类。从 JLS

如果访问是通过限定名称 Q.Id,其中 Q 是 表达式名称,则允许访问当且仅当类型 表达式 Q 是 S 或 S 的子类。

我认为这是人们普遍存在的误解。如果一个类可以访问它自己的属性(如 c1.a,在你的例子中(,那么它有权访问同一类的另一个实例中的同一属性,而不考虑其访问修饰符(甚至是私有的(。例如,这有效:

class Base {
private int x = 0;
public void method(Base other) {
other.x += 5;
}
}

如果你想知道为什么,我想这就是它的设计方式。我想其他支持面向对象设计的语言也一样(我知道它在C++中也是如此(。

注意:这与您的问题无关,但是使用大写的起始词(此处为C1,C2,C4(命名类是一个很好的约定,以便其他人更容易阅读代码。

public class c4 {
public c4() {
c1 c = new c1();
c.a = 60;
}
}

c1public的,因此来自另一个包的c4可以访问它。但是,变量c1.aprotected,这意味着它仅对打包bbbc1的任何子级可见。因此,c.a = 60;CompileTimeError,因为c1.abbb包中不可见,并且c4不会扩展到c1


官方教程可能对您有所帮助。

__
__ |          │ 类 │ 套餐 │ 子类 │ 子类 │ 世界 | |          │ │ │(相同页码(│(差异页码(│ | |───────────┼───────┼─────────┼──────────┼──────────┼────────| |公共 │ + │ + │ + │ + │ + | |───────────┼───────┼─────────┼──────────┼──────────┼────────| |受保护 │ + │ + │ + │ + │ | |───────────┼───────┼─────────┼──────────┼──────────┼────────| |无修饰符│ + │ + │ + │ │ | |───────────┼───────┼─────────┼──────────┼──────────┼────────| |私有 │ + │ │ │ │ │ | |___________|_______|_________|__________|__________|________|  + : 可访问的空白 : 不可访问

最新更新