子类是否继承私有字段?

时间:2011-01-17 17:34:18

标签: java oop inheritance private

这是一个面试问题。

  

子类是否继承私有   字段?

我回答“否”,因为我们无法使用“普通OOP方式”访问它们。但是面试官认为他们是继承的,因为我们可以间接地或使用反射来访问这些领域,但它们仍然存在于对象中。

我回来后,在javadoc

中找到了以下引文
  

超类中的私人会员

     

一个   子类不继承私有   其父类的成员。

你知道面试官的意见吗?

18 个答案:

答案 0 :(得分:222)

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

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

然而。这与类的继承概念不同。正如java世界中存在语义问题的情况一样,仲裁者是Java Language Specification(目前是第3版)。

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

  

声明的类的成员   私人不是继承的   该类的子类。只有会员   声明受保护的类的   或public由子类继承   在除以外的包中声明   宣布上课的人。

这解决了访问者提出的确切问题:“做sub CLASSES 继承私有字段”。 (我强调)

答案是否定的。他们没有。子类的OBJECTS包含其超类的私有字段。子类本身没有其超类私有字段的NO OF。

这是一种迂腐的语义吗?是。这是一个有用的面试问题吗?可能不是。但是JLS建立了Java世界的定义,并且它(在这种情况下)明确地这样做。

EDITED(删除了Bjarne Stroustrup的并行引用,因为java和c ++之间的差异可能只会增加混乱。我会让我的答案依赖于JLS:)

答案 1 :(得分:71)

重要的是要意识到,当两个类时,只有一个对象。

所以,是的,当然它继承了私有领域。它们可能是正确的对象功能必不可少的,虽然父类的对象不是派生类的对象,但派生类的实例绝对是父类的实例。如果没有所有的领域,那就不可能了。

不,您无法直接访问它们。是的,他们是继承的。他们

这是一个很好的问题!


<强> 更新

错误,“不”

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

更新更新:

这里的争议涉及一个基本的模糊性:究竟在讨论什么? 对象?或者我们在某种意义上谈论类本身?< / em>在描述类而不是对象时允许很多纬度。因此,子类不会继承私有字段,但是作为子类实例的对象肯定会包含私有字段。

答案 2 :(得分:18)

没有。私有字段不是继承的...这就是发明 Protected 的原因。这是设计的。我想这证明了保护修饰符的存在。


现在来到这里。你继承的意思是什么 - 如果在派生类创建的对象中存在?是的,它是。

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

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

从功能上讲,它不是继承的。但理想情况,是。


好的,只需查看他们引用的Java教程:

  

超类中的私人会员

     

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

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

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

我认为这纯粹是观点问题。你可以在任何一方塑造争论。这两种方式都更合理。

答案 3 :(得分:11)

这取决于你对“继承”的定义。子类是否仍有内存中的字段?当然。可以直接访问它们吗?不,这只是定义的微妙之处;关键是要了解到底发生了什么。

答案 4 :(得分:10)

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

考虑Dump包中的两个类。孩子延伸父母。

如果我没记错的话,内存中的子对象由两个区域组成。一个是父部分,另一个是子部分。孩子可以进入私人 其父代码中的部分仅通过父代的公共方法。

这样想。波拉特的父亲博尔托克有一个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

答案 5 :(得分:9)

没有。他们不继承它。

其他一些类可能间接使用它的事实没有说继承,而是关于封装。

例如:

class Some { 
   private int count; 
   public void increment() { 
      count++;
   }
   public String toString() { 
       return Integer.toString( count );
   }
}

class UseIt { 
    void useIt() { 
        Some s = new Some();
        s.increment();
        s.increment();
        s.increment();
        int v = Integer.parseInt( s.toString() );
        // hey, can you say you inherit it?
     }
}

您还可以通过反射在count内获取UseIt的值。这并不意味着,你继承了它。

更新

即使值存在,它也不会被子类继承。

例如,子类定义为:

class SomeOther extends Some { 
    private int count = 1000;
    @Override
    public void increment() { 
        super.increment();
        count *= 10000;
    }
}

class UseIt { 
    public static void main( String ... args ) { 
        s = new SomeOther();
        s.increment();
        s.increment();
        s.increment();
        v = Integer.parseInt( s.toString() );
        // what is the value of v?           
     }
}

这与第一个示例的情况完全相同。属性count被隐藏,完全由子类继承。尽管如此,正如DigitalRoss所指出的那样,价值在那里,但不是通过继承手段。

这样说吧。如果你的父亲很富有并且给你一张信用卡,你仍然可以用他的钱买东西,但这并不意味着你有 继承 所有这些钱,是吗?

其他更新

虽然很有意思,to know why the attribute is there.

我坦率地说没有确切的术语来描述它,但它是JVM及其工作方式,也加载了“未继承”的父定义。

我们实际上可以更改父级,子类仍然有效。

For instance

//A.java
class A {
   private int i;
   public String toString() { return ""+ i; }
}
// B.java
class B extends A {}
// Main.java
class Main {
   public static void main( String [] args ) {
      System.out.println( new B().toString() );
    }
}
// Compile all the files
javac A.java B.java Main.java
// Run Main
java Main
// Outout is 0 as expected as B is using the A 'toString' definition
0

// Change A.java
class A {
   public String toString() {
      return "Nothing here";
   }
}
// Recompile ONLY A.java
javac A.java
java Main
// B wasn't modified and yet it shows a different behaviour, this is not due to 
// inheritance but the way Java loads the class
Output: Nothing here

我想确切的术语可以在这里找到:The JavaTM Virtual Machine Specification

答案 6 :(得分:6)

嗯,我对面试官问题的回答是 - 私有成员不是在子类中继承的,但只能通过公共getter或setter方法或任何原始类的适当方法访问子类或子类的对象。< / strong>通常的做法是保持成员私有,并使用公共的getter和setter方法访问它们。那么,当他们处理的私有成员对对象不可用时,只继承getter和setter方法的重点是什么?这里'继承'只是意味着它可以直接在子类中使用,可以通过子类中新引入的方法来实现。

将以下文件保存为ParentClass.java并自行尝试 - &gt;

public class ParentClass {
  private int x;

  public int getX() {
    return x;
  }

  public void setX(int x) {
    this.x = x;
  }
}

class SubClass extends ParentClass {
  private int y;

  public int getY() {
    return y;
  }

  public void setY(int y) {
    this.y = y;
  }

  public void setXofParent(int x) {
    setX(x); 
  }
}

class Main {
  public static void main(String[] args) {
    SubClass s = new SubClass();
    s.setX(10);
    s.setY(12);
    System.out.println("X is :"+s.getX());
    System.out.println("Y is :"+s.getY());
    s.setXofParent(13);
    System.out.println("Now X is :"+s.getX());
  }
}

Output:
X is :10
Y is :12
Now X is :13

如果我们尝试在SubClass的方法中使用ParentClass的私有变量x,那么它不能直接访问任何修改(意味着没有继承)。但是可以通过setXofParent()方法中的原始类的setX()方法在SubClass中修改x,或者可以使用setX()方法或最终调用setX()的setXofParent()方法使用ChildClass对象修改x。所以这里setX()和getX()是ParentClass的私有成员x的一种门。

另一个简单的例子是Clock超类将小时和分钟作为私有成员,并将适当的getter和setter方法作为public。然后DigitalClock作为Clock的子类。如果DigitalClock的对象不包含小时和分钟成员,那么事情就搞砸了。

答案 7 :(得分:4)

好的,这是一个非常有趣的问题,我经常研究并得出结论,超类的私有成员确实可用(但不可访问)子类的对象。为了证明这一点,这里有一个带有父类和子类的示例代码,我正在将子类对象写入txt文件并读取名为&#39; bhavesh&#39;的私有成员。在文件中,因此证明它确实在子类中可用但由于访问修饰符而无法访问。

import java.io.Serializable;
public class ParentClass implements Serializable {
public ParentClass() {

}

public int a=32131,b,c;

private int bhavesh=5555,rr,weq,refw;
}

import java.io.*;
import java.io.Serializable;
public class ChildClass extends ParentClass{
public ChildClass() {
super();
}

public static void main(String[] args) {
ChildClass childObj = new ChildClass();
ObjectOutputStream oos;
try {
        oos = new ObjectOutputStream(new FileOutputStream("C:\\MyData1.txt"));
        oos.writeObject(childObj); //Writing child class object and not parent class object
        System.out.println("Writing complete !");
    } catch (IOException e) {
    }


}
}

打开MyData1.txt并搜索名为&#39; bhavesh&#39;的私人成员。请让我知道你们的想法。

答案 8 :(得分:3)

似乎子类确实继承了私有字段,因为这些字段在子类的内部工作中被用(哲学上讲)。子类在其构造函数中调用超类构造函数。如果超类构造函数在其构造函数中初始化了这些字段,那么超类私有字段显然是由调用超类构造函数的子类继承的。这只是一个例子。但是当然没有访问器方法,子类无法访问超类私有字段(就像无法弹出iPhone的后面板以取出电池来重置手机......但电池仍在那里)。

PS 我遇到的许多继承定义之一: “继承 - 一种编程技术,允许派生类扩展基类的功能,继承其所有的STATE(强调是我的)和行为。”

私有字段,即使子类不可访问,也是超类的继承状态。

答案 9 :(得分:1)

例如,

class Person {
    private String name;

    public String getName () {
        return this.name;
    }

    Person(String name) {
        this.name = name;
    }
}
public class Student extends Person {

    Student(String name) {
        super(name);
    }
    
    public String getStudentName() {
        return this.getName(); // works
        // "return this.name;" doesn't work, and the error is "The field Person.name is not visible"

    }
}

public class Main {
    public static void main(String[] args) {
        Student s = new Student("Bill");

        String name = s.getName(); // works
        // "String name = s.name;" doesn't work, and the error is "The field Person.name is not visible"

        System.out.println(name);
    }
}

答案 10 :(得分:1)

,不会继承私有字段。唯一的原因是子类无法直接访问

答案 11 :(得分:0)

我们可以简单地声明,当继承超类时,超类的私有成员实际上成为子类的私有成员,并且不能进一步继承或无法使用子类的对象。

答案 12 :(得分:0)

我相信,答案完全取决于被问到的问题。我的意思是,如果问题是

  

我们可以直接访问超类的私有字段   他们的子类?

然后回答,如果我们通过access specifier details,则提到私有成员只能在班级内访问。

但是,如果问题是

  

我们可以从中访问超类的私有字段吗?   他们的子类?

这意味着,无关紧要,您将如何访问私有成员。在这种情况下,我们可以在超类中创建公共方法,您可以访问私有成员。因此,在这种情况下,您将创建一个接口/网桥来访问私有成员。

其他OOP语言(如C ++)具有 friend function 概念,我们可以通过该概念访问其他类的私有成员。

答案 13 :(得分:0)

我必须回答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”,那么人们认为它不是继承的。但是,类中的每个非静态事物,无论是字段还是方法,都是继承的。

答案 14 :(得分:0)

私有类成员或构造函数只能在包含成员或构造函数声明的顶级类(§7.6)的主体内访问。它不是由子类继承的。 https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6

答案 15 :(得分:0)

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

参考: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html#:~:text=Private%20Members%20in%20a%20Superclass,be%20used%20by%20the%20subclass

答案 16 :(得分:-1)

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

答案 17 :(得分:-2)

继承私有成员(状态和行为)。它们(可以)影响由类实例化的对象的行为和大小。更不用说它们通过可用的所有封装破坏机制对子类非常清晰可见,或者可以由其实施者承担。

虽然继承具有“defacto”定义,但它绝对没有“可见性”方面的链接,这些方面由“否”答案假设。

所以,没有必要外交。 JLS在这一点上是错的。

任何假设他们不是“继承”都是不安全和危险的。

因此,在两个事实上(部分)冲突的定义中(我不会重复),唯一应该遵循的是更安全(或安全)的定义。