我们可以通过初始化具体的子类来初始化抽象类.因此,应该只能在子类初始化之后才能调用抽象类的抽象方法,然而,抽象类Mammal中的以下初始化块可以在子子类初始化之前调用抽象方法.

如果使用new Platypus()调用Platypus的构造函数,它将输出: "好吃!", "哺乳动物建造者", "鸭嘴兽构造者"的顺序相同.我认为类的实例是在调用构造函数时创建的.但Mammal中的初始化块能够在Platypus初始化之前调用该方法.

abstract class Mammal {

    {
        System.out.println(chew()); 
    }

    abstract CharSequence chew();

    public Mammal() {
       System.out.println("Mammal constructor"); 
    }
}

public class Platypus extends Mammal {

    public Platypus() {
        System.out.println("Platypus constructor");
    }
    
    String chew() {
        return "yummy!";
    }


}

推荐答案

抽象方法在这里没有什么特别之处.您也可以只以相同的方式调用非抽象方法:

class Platypus {
    {
        System.out.println(chew());
    }
    
    public Platypus() {
        System.out.println("Platypus constructor");
    }

    String chew() {
        return "yummy!";
    }
}

我认为类的实例是在调用构造函数时创建的.

不,构造函数不负责creating个对象.首先创建一个对象,然后调用其构造函数来initialise该对象.

这也可以在字节码中看到.new Platypus()的字节码如下所示:

NEW yourpackage/Platypus
DUP
INVOKESPECIAL yourpackage/Platypus.<init> ()V

new指令创建对象,然后调用<init>,这是构造函数的JVM名称.

因此,在这里,我们可以说在对象为fully initialised之前调用了chew().该对象已经存在,因此调用chew在技术上是可行的.

但是,在对象未完全初始化时调用实例方法通常不是一个好主意.该方法可以基于对象被完全初始化的事实(例如,访问预期不为空的字段).另请参阅:Can I call methods in constructor in Java?

Java相关问答推荐

在URL类图中表示Java swing类

Annotation @ Memphier无法正常工作,并表示:class需要一个bean,但找到了2个bean:

查找最大子数组的和

尽管类型擦除,instanceof与泛型在Java中如何工作?

如何获得执行人?

从Spring5迁移到Spring6:无法在雅加达包中找到类

如何从JNI方法正确调用NSOpenPanel以在正确的线程上运行?

与Spring Boot相关的实体未正确保存

JDK 21-为什么线程局部随机S nextInt不直接用Super.nextInt实现?

如何在Java记录中设置BigDecimal类型属性的精度?

如何让JVM在SIGSEGV崩溃后快速退出?

使用Jolt将字段转换为列表

Java泛型类方法的静态返回类型是否被类型擦除?

Android Java:已设置但未读取SharedPreferences

如何处理两个几乎相同的XSD文件?

简化每个元素本身都是 map 列表的列表

[Guice/MissingImplementation]:未绑定任何实现

可以';不要在Intellij IDEA中使用最新的Java版本(JDK 21)

Xml Reader 将 BMP 外部的字符解析为代理项对,这会导致无效的 xml

有没有办法仅将 JComboBox 中的选定项目居中(因此保持组合框中的所有项目左对齐)