第一点
它是一种在创建对象时自动调用的方法。将其视为对象构造的侦听器。
第二点
子类必须在第一条语句中调用父构造函数。构造函数是对象的初始化器。正如我所说,它可以被认为是一个对象构造监听器。
参数
构造函数接受的参数取决于调用者如何构造对象,而对于抽象类参数,子类如何转发参数super(...)
实际上是子类如何扩展超类的类定义的一部分。这也解释了super();
如果超类构造函数不接受参数,为什么没有必要。
第三点
抽象类是类。
抽象类也是类;不要歧视他们。类是包含类字段和类方法的东西;这是类的基本定义,因此类的实例称为对象。抽象类满足这一点;只是它的一些方法不是实际的方法,但从调用者的角度来看它们仍然是方法。例如,调用者在调用一个方法时不需要知道它是否是抽象的。
C++ 比较
如果我们查看 C++,(其中 afaik 是 Java 类的源代码/灵感/模型/任何东西),我们会发现类方法不一定有实现(尽管如果没有实现,则会出现错误,忘记运行时或编译时间)但只有原型。Javaabstract
方法就像没有原型的 C++ 方法。(我对 C++ 没有经验,所以这部分可能不准确)
这表明,abstract
抽象类中的含义仅意味着它(i)不能被实例化并且(ii)可以包含抽象方法。超类中的抽象方法意味着该方法应该存在,但子类必须自己实现;并且由于无法实例化抽象类,因此可以安全地在其中包含一个abstract
(或者如果这让您感到恼火,请将其视为空/return null
方法)方法。
接口呢?
另一方面,Java 接口基本上定义了预期将出现在实现类中的方法列表,但接口本身实际上不是一个类。
为什么没有构造方法?
为什么你甚至想要那个?您不会从接口的名称中实例化对象。
如果您正在考虑限制构造函数中的参数,例如registerSubclass(Class<? extends ThisSuperclass>)
寄存器类型 API 的类型,您可能会有这样的代码:
abstract class Handler{
public static <T> void registerHandler(Class<T extends Handler> clazz){
Constructor<T> c = clazz.getConstructor(Event.class); // say, you have to construct subclasses to handle an event
// a lot of try-catch trouble
}
}
但是,到目前为止,Java 中不存在此功能,您必须自己检查构造函数(至少据我所知)。
默认方法呢?
Java 8 中添加了默认方法,其中接口可以具有具体方法。我不熟悉此新功能的概念或边缘案例,但参考 Java 文档中关于接口的“汽车”类比,如果interface Car
客户对您需要生产的产品的需求,以便他们购买您的汽车,默认界面中的方法就像“我要在车上开空调,但因为对你来说可能很难,所以我给你这个我发明的空调系统;你可以再做一个空调系统”。
为什么接口中没有默认构造函数?
正如我所提到的,构造函数就像对象构造的侦听器,因此从这个角度来看,它不是方法,而是类结构的一部分(如extends
子句、注释或类的其他修饰符)。接口定义了您需要的方法。默认方法只是一个虚拟方法,主要用于接口的向后兼容性。但是对于默认构造函数来说是非常不合理的,因为它不是这个意义上的方法。
免责声明:我从来没有从教程中正确地学习过Java,所以我的理解来自我自己2年多的观察,但到目前为止,这似乎正确解释了Java类。在实际编程中,只要语义正确,这些概念并不重要,尽管如果您理解了这些概念,则更容易正确理解语义。