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的子类