【问题标题】:Private method defined in `Sub` and `Super`, both methods can be invoked on Object of Sub , then why private method said not being inherited?`Sub` 和 `Super` 中定义的私有方法,这两个方法都可以在 Sub 的 Object 上调用,那为什么私有方法说不被继承呢?
【发布时间】:2025-12-06 23:20:08
【问题描述】:

根据Oracle Tutorials

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

[问题] 对于Sub extends Super 的类关系, 据了解,Oracle 文档这样说只是为了支持“只能重写继承的方法”这一事实,但这是一种 误导 声明,好像它似乎暗示 => 如果方法不是继承的,那么它就不会作为 Sub 类对象的行为存在,如果是这样,那么它决不能在 Sub 类的对象上调用。但是 Super 类中的方法可以调用 Super 类在 Sub 类的 Object 上定义的私有方法。 请参考以下几点和相关代码,并提出我的理解是否存在差距?

我一直把继承理解为以下3点

  1. Sub 继承所有实例方法和字段(包括私有的)。
  2. 如果一个方法在Super 中是私有的,那么它在Sub 中是不可见的,但这并不意味着Sub 的对象没有该行为。

第 1 点和第 2 点的代码

public class Super{
    private void privateMethod(){
        System.out.println("private method defined in Super");
    }
    public void m(){
        privateMethod();
    }
}

public class Sub extends Super{

} 
public void Other{
    public static void main(String[] args){
        Sub s = new Sub();
        s.m(); 
    }
}

我们创建了一个Sub的对象,m()Sub继承,它的public意味着它可以被Super之外的代码访问。在调用m() 时,我们可以调用privateMethod()。如果私有方法没有被继承,那么就会发生一些运行时异常,但事实并非如此。

  1. Overriding 仅适用于Sub 类中的可见 实例方法。如果一个方法是不可见的,并且在SubSuper 这两个类中都定义了,那么该对象具有这两种能力,并且这两种方法都可以由可以访问特定方法的代码调用(参考下面的代码)

第 3 点的代码

public class Super{
    private void privateMethod(){
        System.out.println("private method defined in Super");
    }
    public void m(){
        privateMethod();
    }
}

public class Sub extends Super{
    private void privateMethod(){
        System.out.println("private method defined in Sub");
    }
    public void m2(){
        privateMethod();
    }
} 
public class Other{
    public static void main(String[] args){
        Sub s = new Sub();
        s.m(); // m() will invoke private method of Super
        s.m2(); // m2() will invoke private method of Sub
    }
}

Sub 类不从Super 继承私有方法意味着不能在Sub 的对象上调用方法,因为该行为不是继承的,因此不是(不属于)对象的一部分.上面我们看到情况并非如此。

【问题讨论】:

  • 您可能想要更改Sub 类方法的输出。去掉方法,Sub实例不可用,也不能直接从Other调用,就是这个意思。
  • @daniu 请详细说明您指的是什么方法,我已经编辑了问题以便更好地理解。

标签: java inheritance private-methods


【解决方案1】:

我认为主要区别在于 Java 语言规范如何使用“继承”一词。 (请注意,JLS 是权威文档,而不是 Java 教程。)

JLS 8.2, Class Members 说:

声明为私有的类的成员不会被该类的子类继承。

但是,在描述 new 运算符的行为时,JLS 15.9.4, Run-Time Evaluation of Class Instance Creation Expressions 说(强调我的):

新对象包含在指定类类型及其所有超类中声明的所有字段的新实例。

这意味着超类的字段不是由子类继承,但子类的实例对象仍然包含这些字段。同样的概念也适用于私有方法

虽然可以在子类的实例上调用来自超类的私有方法,但该方法在形式上并不是该子类的一部分。 私有方法仍然属于超类。

这是因为子类型(“is-a”)关系。子类型的实例超类型的实例。 该类不会将这些成员继承到自身中,但该类的一个实例仍然包含它们。

【讨论】:

  • 谢谢,我在阅读您的回答后所做的第一次编辑:更正了错误:将引用的语句称为 oracle 文档而不是 oracle 教程。另外我觉得最好使用单词包含(子对象包含超类中私有的方法,如果两个类具有相同的方法,则它包含它们并且将根据调用代码调用方法)。
【解决方案2】:

在您给出的示例中,来自类SuperprivateMethod 确实是私有的,不能被Sub 继承。这样的设计意味着我们不希望子类能够具有 privateMethod 行为,这就是为什么将 privateMethod 包装在公共方法中是不合逻辑的,然后 Sub 类可以执行并具有“私有行为” ”。 所以这个实现不会在现实生活中使用。

并且由于privateMethod 不是由Sub 继承的,因此其中实现的privateMethod 不是覆盖,而是恰好具有相同签名的方法。如果您没有在Sub 中定义方法,您将无法使用s.m2()(即s.privateMethod())。

但是 Super 类中的方法可以调用由定义的私有方法 超级类

这就是它的本意:任何类都可以使用自己定义的方法,无论是公共的还是私有的。

【讨论】:

  • 其实和你说的相反。如果私有方法没有包含在任何非公共方法中,那么私有方法就没有多大用处。它是定义类与依赖类或用户类的契约的公共方法,内部实现是在私有方法中完成的。您可以参考 java.util.ArrayList 中的“ensureCapacity”它的 Public 方法,它使用私有的 grow() 方法。这只是一个例子
  • @Ety 总是私有方法必须是从调用公共方法或公共构造函数开始的方法调用的一部分才能有用。请参阅 java.util.ArrayList 中的“ensureCapacity”它的 Public 方法,它使用私有的 grow() 方法。 (我评论是因为您说将 privateMethod 包装在公共方法中是不合逻辑的......)
  • @Daniel Pryden 我已删除该评论并重新措辞
最近更新 更多