这是面试问题。

子类继承private吗 字段?

我的回答是“不”,因为我们不能使用“正常的面向对象的方式”访问它们。但是采访者认为它们是继承的,因为我们可以间接或使用反射访问这些字段,并且它们仍然存在于对象中。

回来后,我在javadoc中找到了以下引用:

超类中的私人成员 一个 子类不继承私有 父类的成员。

你知道面试官观点的论据吗?


当前回答

我将用代码演示这个概念。子类实际上继承了父类的私有变量。唯一的问题是他们不能访问 子对象,除非您为私有变量提供公共getter和setter 在超级班。

考虑包转储中的两个类。子扩展父。

如果我没记错的话,内存中的子对象由两个区域组成。一个是父部分,另一个是子部分。子程序可以访问私有文件 节只能通过父类中的公共方法在其父类的代码中调用。

这样想。波拉特的父亲博尔托克有一个装有10万美元的保险箱。他不想共享他的“私有”变量保险箱。所以,他没有提供保险箱的钥匙。波拉特继承了保险箱。但是,如果他连门都打不开,那又有什么用呢?要是他的 爸爸提供了钥匙。

父母,

package Dump;

public class Parent {

    private String reallyHidden;
    private String notReallyHidden;

    public String getNotReallyHidden() {
        return notReallyHidden;
    }

    public void setNotReallyHidden(String notReallyHidden) {
        this.notReallyHidden = notReallyHidden;
    }

}//Parent

孩子,

package Dump;

public class Child extends Parent {

    private String childOnly;

    public String getChildOnly() {
        return childOnly;
    }

    public void setChildOnly(String childOnly) {
        this.childOnly = childOnly;
    }

    public static void main(String [] args){

        System.out.println("Testing...");
        Child c1 = new Child();
        c1.setChildOnly("childOnly");
        c1.setNotReallyHidden("notReallyHidden");

        //Attempting to access parent's reallyHidden
            c1.reallyHidden;//Does not even compile

    }//main

}//Child

其他回答

Yes

重要的是要认识到,虽然有两个类,但只有一个对象。

当然,它继承了私有字段。它们大概是正确的对象功能所必需的,虽然父类的对象不是派生类的对象,但派生类的实例基本上肯定是父类的实例。如果没有所有的领域,就不可能是这样。

不,你不能直接访问它们。是的,它们是遗传的。他们必须如此。

这是个好问题!


更新:

呃,“不”

我想我们都学到了一些东西。由于JLS提出了确切的“不继承”措辞,所以回答“不继承”是正确的。由于子类不能访问或修改私有字段,因此,换句话说,它们不会被继承。但实际上只有一个对象,它确实包含私有字段,因此如果有人以错误的方式使用JLS和教程措辞,将很难理解OOP、Java对象以及实际发生的事情。

更新更新:

这里的争议涉及到一个根本的模糊:讨论的究竟是什么?的对象?或者我们在某种意义上谈论的是类本身?当描述类而不是对象时,允许有很大的自由度。因此,子类不继承私有字段,但作为子类实例的对象当然包含私有字段。

我必须回答,Java中的私有字段是继承的。请允许我演示一下:

public class Foo {

    private int x; // This is the private field.

    public Foo() {
        x = 0; // Sets int x to 0.
    }

    //The following methods are declared "final" so that they can't be overridden.
    public final void update() { x++; } // Increments x by 1.
    public final int getX() { return x; } // Returns the x value.

}


public class Bar extends Foo {

    public Bar() {

        super(); // Because this extends a class with a constructor, it is required to run before anything else.

        update(); //Runs the inherited update() method twice
        update();
        System.out.println(getX()); // Prints the inherited "x" int.

    }

}

如果你在一个程序中运行Bar Bar = new Bar();,那么你总是会在输出框中看到数字“2”。由于整数“x”被update()和getX()方法封装,因此可以证明该整数是继承的。

令人困惑的是,因为不能直接访问整数“x”,所以人们认为它不是继承的。然而,类中的每一个非静态的东西,无论是字段还是方法,都是继承的。

我可以试着帮你。 当一个子类(例如命名为B)扩展一个超类(例如命名为a)时,它自动从它的超类继承字段(例如属性和/或方法)。 现在,B在它的内存布局中为类A中的每个字段提供了空间,包括私有字段。事实上,Java不允许子类B使用私有字段,因为它们是私有的。

这里的问题/答案中的大多数困惑都围绕着继承的定义。

显然,正如@DigitalRoss解释的那样,子类的OBJECT必须包含其父类的私有字段。正如他所说,无法访问私人会员并不意味着它不存在。

然而。这与类继承的概念不同。在java世界中,存在语义问题时,仲裁人是java语言规范(目前是第3版)。

正如JLS所述(https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):

已声明的类的成员 Private不被继承 该类的子类。只有成员 声明为受保护的类的 或public由子类继承 类以外的包中声明 声明类的语句。

这就解决了采访者提出的问题:“子类继承私有字段吗?”(我强调了一下)

答案是否定的。他们没有。子类的对象包含父类的私有字段。子类本身没有父类的私有字段的概念。

这是学究性质的语义学吗?是的。这是个有用的面试问题吗?可能不会。但是JLS为Java世界建立了定义,并且这样做(在本例中)是明确的。

编辑(删除了Bjarne Stroustrup的平行引用,由于java和c++之间的差异,这可能只会增加混淆。我将让我的答案取决于JLS:)

不。私有字段没有被继承…所以我们才发明了"保护"这是有意为之。我想这证明了受保护修饰符的存在。


现在来看看上下文。继承是什么意思——如果它存在于从派生类创建的对象中?是的,它是。

如果你的意思是它是否对派生类有用。嗯,没有。

现在,当你进行函数式编程时,父类的私有字段不会以一种有意义的方式继承给子类。对于子类,超类的私有字段与任何其他类的私有字段相同。

在功能上,它不是遗传的。但理想情况是这样的。


好吧,刚刚看了一下Java教程,他们引用了这样的话:

超类中的私人成员 子类不继承父类的私有成员。但是,如果父类具有用于访问其私有字段的公共或受保护方法,则子类也可以使用这些方法。

参见:http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html

我同意,这个领域是存在的。但是,子类在私有字段上没有任何特权。对于子类,私有字段与任何其他类的私有字段相同。

我相信这只是个人观点的问题。你可以左右争论的任何一方。这两种方法都是合理的。