java - Java 中的子类型会导致意外的输出

标签 java oop subtyping

我尝试了解子类型和继承在 Java 中的工作原理。最近我遇到了一个让我很困惑的情况。我得到了以下包含三个类的代码:

class Super{
    String i = "Variable of superclass";
    void m() {
        System.out.println(i);
    }
}



class Sub extends Super{
    String i = "Variable of subclass";
    
    /*@Override
    void m() {
        System.out.println(i);
    }*/

}



public class Main {
    public static void main(String[] args) {
                Sub sub = new Sub();
        sub.m();    //Prints Variable of superclass
    }   
}

我对 m() 的输出很困惑。我只是不明白为什么在 Sub 实例上调用的方法使用父类(super class)的变量。我想这与变量隐藏/阴影有关,但我无法弄清楚那里到底发生了什么。如果我做类似的事情

Super sup = new Sub();
sup.m();

然后我明白了,为什么它打印父类(super class)的变量。这是因为变量以静态方式绑定(bind),我称之为变量隐藏/阴影。但我真的不明白,在我的例子中发生了什么。

当我删除 Sub 中的评论时,我对发生的事情更加困惑。我知道该方法现在已被重写,但我不明白为什么该方法现在使用子类的变量,即使它与如果我留下注释而继承的代码完全相同。我的意思是,它已经在那里了!使用完全相同的代码重写方法会如何改变任何内容?

我还尝试在方法内添加 System.out.println(this.getClass.getName()); 以确保确实在 sub 实例上调用该方法。是的,确实如此。

如果有人能帮助我理解这里发生了什么,我将非常感激!

最佳答案

方法可以被覆盖,但字段不能。 Sub没有定义m方法,所以sub.m();调用m方法来自Super 。在该方法的范围内,只有 i Super 中定义的字段本身是可见的。

i Sub 中定义的字段是一个不同的字段,它隐藏了同名父类(super class)的字段。如果您定义了 getI()两者中的方法 SuperSub ,调用 getI()Super (当底层实例的类型为 Sub 时)将使用 Sub 中定义的方法.

关于java - Java 中的子类型会导致意外的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76838232/

相关文章:

java - 正则表达式提取内容类型

java - 匹配出现次数最多的字符串

php - 使用名称中带有变量的命名空间

android - 外部Sqlite数据库,无法插入数据库,android studio

java - 使用 super 的方法可以获取对象的子类型并将其添加到列表中吗?

java - 将 ArrayList 的内容写入文本文件

PHP OOP 插入数据

rust - 在 Rust 中与生命周期的子类型关系作斗争

scala - 从非协变类的实例创建协变类型类的实例

java - 将 Spring-Security PasswordEncoder 与默认身份验证提供程序一起使用?