这是一个面试问题。
子类会继承私有字段吗?
我回答“不会”,因为我们不能使用“常规的OOP方法”访问它们。但是面试官认为它们被继承了,因为我们可以间接或使用反射访问这些字段,并且它们仍然存在于对象中。
当我回来后,在javadoc中找到了以下引用:
超类中的私有成员
子类不会继承其父类的私有成员。
你知道面试官观点的任何论据吗?
这是一个面试问题。
子类会继承私有字段吗?
我回答“不会”,因为我们不能使用“常规的OOP方法”访问它们。但是面试官认为它们被继承了,因为我们可以间接或使用反射访问这些字段,并且它们仍然存在于对象中。
当我回来后,在javadoc中找到了以下引用:
超类中的私有成员
子类不会继承其父类的私有成员。
你知道面试官观点的任何论据吗?
类声明为private的成员不会被该类的子类继承。只有声明为protected或public的类成员才会被声明在与该类不同的包中的子类继承。这回答了面试官提出的确切问题:"子类是否继承私有字段"。(由我强调)
需要意识到,虽然有两个类,但只有一个对象。
所以,是的,它继承了私有字段。它们可能是适当的对象功能所必需的,虽然父类的对象不是派生类的对象,但派生类的实例绝大部分都是父类的实例。没有所有字段就不能这样做。
不能直接访问它们,但它们确实被继承了。它们必须继承。
这是个好问题!
更新:
好吧,我想我们都学到了些什么。由于JLS采用了精确的“未继承”措辞,回答“不”是正确的。由于子类无法访问或修改私有字段,因此可以说它们并未被继承。但实际上只有一个对象,它确实包含了私有字段,因此如果有人错误地理解JLS和教程中的措辞,将很难理解OOP、Java对象以及真正发生的事情。
更新更新:
这里涉及到一个基本的模糊性:究竟讨论的是什么?对象?还是在某种意义上谈论类本身?当描述类而不是对象时,可以允许很大范围的内容。因此,子类不继承私有字段,但是作为子类实例的对象肯定包含私有字段。
非私有字段不会被继承...这就是为什么Protected被发明出来的原因。这是按设计需求实现的。我想这证明了protected修饰符的存在。
现在进入具体情境。如果您指的是从派生类创建的对象中是否存在继承,那么是的,它存在。
如果您的意思是派生类是否可以使用它,那么不行。
现在谈到函数式编程,超类的私有字段不能以有意义的方式被子类继承。对于子类而言,超类的私有字段与任何其他类的私有字段相同。
从功能上讲,它并没有被继承。但是理论上,它被继承了。
好的,刚刚查看了Java教程内容,他们引用了以下内容:
父类中的私有成员
子类不会继承其父类的私有成员。但是,如果父类具有公共或受保护的方法来访问其私有字段,则子类也可以使用这些方法。
参考:http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html
我同意,该字段存在。但是,子类对该私有字段没有任何特权。对于子类而言,私有字段与任何其他类的私有字段相同。
我认为这纯粹是观点问题。您可以将论据塑造成任何一方。最好两种方式都能证明。
这取决于您对“继承”的定义。子类是否仍然在内存中具有相应的字段?肯定是有的。它是否可以直接访问它们?不行。这只是定义的微妙之处;关键是要理解实际发生了什么。
我将用代码演示这个概念。子类实际上继承了超类的私有变量。唯一的问题是,除非您在超类中提供公共的getter和setter来访问私有变量,否则它们对子对象不可访问。
考虑Dump包中的两个类。Child继承Parent。
如果我没记错的话,在内存中,子对象由两个区域组成。一个是仅属于父类部分,另一个是仅属于子类部分。子类只能通过父类中的公共方法访问其父类代码中的私有部分。
可以这样想。Borat的父亲Boltok有一个保险柜,里面有10万美元。他不想分享他的“私有”保险柜。所以,他没有提供保险柜的钥匙。Borat继承了这个保险柜。但是,如果他甚至无法打开它,那还有什么用呢?如果他的父亲提供了钥匙就好了。
父类 -
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
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?
}
}
您还可以通过反射在UseIt
内获取count
的值。这并不意味着您继承了它。
更新
即使该值存在,子类也不会继承它。
例如,一个定义为:
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所指出的那样,该值仍然存在,但不是通过继承手段而来。//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
我猜这个确切的术语可以在这里找到:Java虚拟机规范
封装
和 继承
的优劣的观点非常棒,我想这个回答应该得到更多的赞同。 - Eric请将以下文件保存为ParentClass.java并尝试运行:
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
好的,这是一个非常有趣的问题。经过我的研究,我得出了一个结论:父类的私有成员确实可以在子类对象中使用(但不可访问)。为了证明这一点,我写了一个包含父类和子类的示例代码,并将子类对象写入到一个文本文件中,然后读取了文件中名为“bhavesh”的私有成员,从而证明它确实在子类中可用,但由于访问修饰符而不可访问。
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文件,查找名为“bhavesh”的私有成员。请告诉我你们的想法。
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);
}
}