这是一个面试问题。
子类是否继承私有字段?
我回答“否”,因为我们无法使用“常规OOP方式”访问它们。但是访问者认为它们是继承的,因为我们可以间接或使用反射来访问这些字段,并且它们仍然存在于对象中。
回来后,我在javadoc中找到了以下引号:
超类私人成员
子类不继承其父类的私有成员。
你知道面试官的观点有什么论据吗?
这是一个面试问题。
子类是否继承私有字段?
我回答“否”,因为我们无法使用“常规OOP方式”访问它们。但是访问者认为它们是继承的,因为我们可以间接或使用反射来访问这些字段,并且它们仍然存在于对象中。
回来后,我在javadoc中找到了以下引号:
超类私人成员
子类不继承其父类的私有成员。
你知道面试官的观点有什么论据吗?
Answers:
这里的问题/答案中的大多数困惑都围绕着继承的定义。
显然,正如@DigitalRoss解释的那样,子类的对象必须包含其超类的私有字段。正如他所说,无法访问私人成员并不意味着它不存在。
然而。这与类的继承概念不同。就像Java世界中的情况一样,存在语义问题的仲裁者是Java语言规范(当前为第3版)。
如JLS所述(https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):
声明为私有的类的成员不会被该类的子类继承。只有声明为protected或public的类的成员才能被声明为非包中声明的包的子类继承。
这解决了面试官提出的确切问题:“做子类继承私有字段”。(我加强调)
答案是否定的。他们没有。子类的对象包含其超类的私有字段。子类本身没有其父类的私有字段的NO NOTION。
它是学究性的语义吗?是。这是一个有用的面试问题吗?可能不是。但是JLS为Java世界建立了定义,并且它确实做到了(在这种情况下)。
编辑(从Bjarne Stroustrup中删除了一个并行引用,由于Java和c ++之间的差异,这可能只会增加混乱。我将答案放在JLS上:)
认识到,虽然有很重要的两个班,只有一个对象。
因此,是的,它当然继承了私有字段。大概它们对于正确的对象功能是必不可少的,并且父类的对象不是派生类的对象,而派生类的实例绝大部分肯定是父类的实例。如果没有所有领域,那就不是很好。
不,您不能直接访问它们。是的,它们是继承的。他们必须是。
这是一个好问题!
更新:
好吧,我想我们大家都学到了一些东西。由于JLS起源于确切的“未继承”用语,因此回答“否”是正确的。由于子类无法访问或修改私有字段,因此,它们不会被继承。但是,真的是只是一个对象,它真的确实包含了私人领域,因此,如果有人花JLS和教程措辞错误的方式,这将是相当困难的理解面向对象,Java对象,什么是真正发生。
更新更新:
这里的争议涉及一个基本的模棱两可:到底在讨论什么?该对象? 还是我们在某种程度上谈论班级本身? 描述类而不是对象时,可以有很大的自由度。因此,子类不会继承私有字段,但是作为子类实例的对象肯定会包含私有字段。
car
,他把它放在private
孩子没有钥匙的储物柜中。您确实继承了,car
但是对您没有用。因此,实际上,您没有从继承中受益。
不会。私有字段不会被继承...这就是为什么发明了Protected的原因。这是设计使然。我想这证明了受保护修饰符的存在。
现在来看上下文。继承是什么意思-如果在派生类创建的对象中存在继承?是的。
如果您的意思是对派生类有用。好吧,不。
现在,当您进行函数编程时,对于子类而言,超类的私有字段不会以有意义的方式继承。对于子类,超类的私有字段与任何其他类的私有字段相同。
从功能上讲,它不是继承的。但理想情况下是这样。
好的,只是看了看Java教程,他们引用了这一点:
超类私人成员
子类不继承其父类的私有成员。但是,如果超类具有用于访问其私有字段的公共或受保护的方法,则子类也可以使用这些方法。
请参阅:http : //download.oracle.com/javase/tutorial/java/IandI/subclasses.html
我同意,那个领域在那里。但是,子类在该私有字段上没有任何特权。对于子类,私有字段与任何其他类的任何私有字段相同。
我认为这纯粹是观点问题。您可以在任一侧修改参数。最好同时证明这两种情况。
I believe it's purely matter of point-of-view.
和justified the existence of protected modifier.
这取决于您对“继承”的定义。子类中是否仍存在字段?绝对是 它可以直接访问它们吗?不。这只是定义的微妙之处。关键是要了解实际情况。
我将通过代码演示该概念。子类实际上继承了超类的私有变量。唯一的问题是,除非您为超类中的私有变量提供公共获取器和设置器,否则子对象无法访问它们。
考虑包Dump中的两个类。孩子扩展了父级。
如果我没记错的话,内存中的子对象由两个区域组成。一个仅是父部分,另一个仅是子部分。子级只能通过父级中的公共方法访问其父级代码中的私有部分。
这样想吧。Borat的父亲Boltok拥有一个装有$ 100,000的保险箱。他不想共享自己的“私有”变量安全。因此,他没有提供保险箱的钥匙。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?
}
}
您还可以通过反射获得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所指出的那样,值仍然存在,但不是通过继承来实现的。
这样说。如果您父亲有钱并且给您一张信用卡,您仍然可以用他的钱来买东西,但这并不意味着您已经继承了所有的钱,对吗?
其他更新
但是,知道为什么存在该属性非常有趣。
坦率地说,我没有确切的术语来描述它,但这是JVM及其工作方式还加载了“未继承的”父定义。
我们实际上可以更改父级,子类仍然可以工作。
例如:
//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
我猜确切的术语可以在这里找到: JavaTM虚拟机规范
encapsulation
VS inherit
,我想这个答案应该多了起来投票。
好吧,我对访调员问题的回答是:私有成员不继承于子类,但子类或子类的对象只能通过公共getter或setter方法或原始类的任何此类适当方法访问它们。通常的做法是使成员保持私密,并使用公开的getter和setter方法访问成员。那么,当对象处理的私有成员不可用时,仅继承getter和setter方法有什么意义呢?这里的“继承”只是意味着它可以在子类中直接使用,以通过子类中新引入的方法进行操作。
将以下文件另存为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
如果我们尝试在SubClass的方法中使用ParentClass的私有变量x,则无法直接对其进行任何修改(意味着未继承)。但是x可以通过原始类的setX()方法在SubClass中进行修改,就像在setXofParent()方法中所做的一样,也可以使用ChildClass对象使用setX()方法或setXofParent()方法进行修改,最终调用setX()。因此,这里的setX()和getX()是对ParentClass的私有成员x的一种门。
另一个简单的示例是Clock超类,其小时和分钟作为私有成员,而适当的getter和setter方法作为public。然后是DigitalClock作为Clock的子类。在这里,如果DigitalClock的对象不包含小时和分钟成员,那么事情就搞砸了。
好的,这是我研究的一个非常有趣的问题,得出的结论是,超类的私有成员确实可以在子类的对象中使用(但不能访问)。为了证明这一点,这是一个带有父类和子类的示例代码,我将子类对象写入txt文件,并读取文件中名为“ 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”的私人成员。请让我知道你们的想法。
我将不得不回答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”,所以人们认为它不是继承的。但是,类中的每个非静态事物,无论是字段还是方法,都是继承的。
我相信,答案完全取决于所提出的问题。我的意思是,如果问题是
我们可以直接从其子类访问父类的私有字段吗?
然后答案是“ 否”,如果提到访问说明符details,则提到私有成员只能在类本身内访问。
但是,如果问题是
我们可以从其子类访问父类的私有字段吗?
也就是说,访问私有成员将执行什么操作都没有关系。在这种情况下,我们可以在超类中设置公共方法,而您可以访问私有成员。因此,在这种情况下,您将创建一个接口/桥来访问私有成员。
其他的OOP语言(例如C ++)也有这个friend function
概念,通过它我们可以访问其他类的私有成员。
私有类成员或构造函数只能在包含该成员或构造函数声明的顶级类(第7.6节)的主体内访问。它不是子类继承的。https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6
私有成员(状态和行为)被继承。它们(可以)影响由类实例化的对象的行为和大小。更不用说它们通过所有可用的或可以由其实现者假定的破译机制对子类很好地看到。
尽管继承具有“事实上的”定义,但它绝对没有指向“可见性”方面的链接,这些方面由“否”答案来承担。
因此,无需外交。JLS在这一点上是错误的。
任何不“继承”它们的假设都是不安全和危险的。
因此,在两个事实上的(部分)冲突的定义(我将不再重复)中,唯一应遵循的定义是更安全(或更安全)的定义。