Java - 子类无法访问受保护的字段? [复制]

Posted

技术标签:

【中文标题】Java - 子类无法访问受保护的字段? [复制]【英文标题】:Java - Protected field not accessible from the subclass? [duplicate] 【发布时间】:2015-05-09 13:19:07 【问题描述】:

我正在学习 Java 访问修饰符。为此,我创建了一个类Machine

package udemy.beginner.interfaces;

public class Machine 

    public String name;
    private int id;
    protected String description;
    String serialNumber;

    public static int count;

    public Machine()
        name = "Machine";
        count++;
        description = "Hello";
    


然后,在另一个包中,我创建了一个类Robot作为汽车Machine的子类:

package udemy.beginner.inheritance;

import udemy.beginner.interfaces.Machine;

public class Robot extends Machine 

    public Robot()

        Machine mach1 = new Machine();
        String name = mach1.name;
        //here I am getting error "The field Machine.description is not visible" 
        String description = mach1.description; 
    


尝试访问 Robot 类中的字段 description 时出现错误。根据我对protected 访问修饰符如何工作的理解,它应该没问题,但也许我搞砸了。有什么想法吗?


编辑:我试图将Robot 类移动到与Machine 类所在的包相同的包中,现在它可以工作了,无需使用它。如果有人可以解释我this。根据下面的答案,它不应该也能正常工作......

【问题讨论】:

protected 表示:来自继承的类并且在同一个包中。下面的 6.6.2 说:对象的受保护成员或构造函数只能通过负责该对象的实现。 从包内部可以访问它。 【参考方案1】:

您不能在该类的不同实例中访问受保护的超类字段。

有一个很好的理由:您不知道它是否与您具有相同的子类,还是完全不同的子类。如果允许它访问受保护的字段,您将被允许访问完全不相关的类的内部。

如果您确定该对象与要访问超类字段的类属于同一子类,则可以强制转换该对象;当您这样做时,您可以访问受保护的字段。

规则在Java Language Specification section 6.6.2中描述

6.6.2。受保护访问的详细信息

对象的受保护成员或构造函数只能通过以下代码从声明它的包外部访问 负责该对象的实现。

6.6.2.1。访问受保护的成员

令 C 为声明受保护成员的类。访问是 只允许在 C 的子类 S 的主体内。

另外,如果Id表示实例字段或实例方法,那么:

如果通过限定名称 Q.Id 进行访问,其中 Q 是 ExpressionName,则当且仅当类型为 表达式 Q 是 S 或 S 的子类。 [这是相关部分]

【讨论】:

还有一个问题——如果我们可以通过超类中定义的 getter/setter 方法访问受保护的访问修饰符,为什么还要使用它??? 有时您不想创建 getter/setter,因为其他类不应直接访问该字段。试着想一个例子 - 假设你有一个 List 类,并且有一个字段 length,那么你不想要一个 setLength 方法,因为 length 字段是由于其他操作而修改的,例如addremove.【参考方案2】:

protected 变量可以在类外部访问,但只能通过继承。因此,如果您将该语句更改为:

public Robot()

    Machine mach1 = new Machine();
    String name = mach1.name;
    // This will work (access on `this` reference)
    String description = this.description; 

实际上protected修饰符的意思是,该字段是可见的,可以被子类继承,并且只能在那里使用,使用this引用。

【讨论】:

以上是关于Java - 子类无法访问受保护的字段? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

受保护的字段对子类不可见

为啥 Java 反射 API 允许我们访问私有和受保护的字段和方法?这不会破坏访问修饰符的目的吗? [复制]

无法访问子类中的受保护方法[重复]

在 kotlin 中,如何从子类访问父类中受保护的静态成员

从包外的子类访问受保护的变量

我可以在 Java 中公开受保护的成员吗?我想从子类访问它