这是面试问题。

子类继承private吗 字段?

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

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

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

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


当前回答

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


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

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

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

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


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

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

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

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

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

 

其他回答

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

不。他们没有继承。

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

例如:

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?           
     }
}

这和第一个例子的情况完全一样。属性计数是隐藏的,根本不被子类继承。不过,正如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

我想确切的术语可以在这里找到:java虚拟机规范

填充位/对齐和VTABLE中对象类的包含不被考虑。因此,子类的对象确实为超类的私有成员留有一席之地。但是,它不能从子类的对象中访问…

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

参考: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html: ~:文本=私人% 20成员在% 20 % % 20 20超类,由% % 20使用% 20 20 % 20子类。

私有成员(状态和行为)是继承的。它们(可以)影响类实例化的对象的行为和大小。更不用说,通过所有可用的封装破坏机制,或者它们的实现者可以假定,子类可以很好地看到它们。

虽然继承有一个“事实上的”定义,但它肯定与“可见性”方面没有联系,这是“不”答案所假设的。

所以,没有必要采取外交手段。JLS在这一点上是错误的。

任何认为他们不是“遗传”的假设都是不安全的和危险的。

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