【问题标题】:Why does Java allow a constructor to invoke abstract and non-final methods?为什么 Java 允许构造函数调用抽象和非最终方法?
【发布时间】:2016-12-17 05:42:06
【问题描述】:

Java 允许非最终类的构造函数调用任何实例方法,即使这些方法是抽象的或非最终的。

这被认为是一种不好的做法(参见,例如,Effective Java 2nd Edition,Item 17),并且由于定义的构造函数顺序,在 C++ 中是不可能的。

我的问题是为什么在 Java 语言的设计中允许这样做?似乎它可以作为语言限制被禁止。是否有必要这样做?

【问题讨论】:

  • 使编译更加困难。 Just don't do it.
  • 如何让编译变得更加困难?如果该语言有“构造函数只能调用私有或最终实例方法”之类的限制,那么在编译时似乎应该很容易验证。我问这个问题是因为我正在研究很多广泛执行此操作的遗留代码,所以我想知道为什么这可以开始。
  • 这是不好的做法,原因与泄露this
  • 为了这个问题,除了引用来源之外,最好包括(您认为)它不好的实际原因。而不是仅仅说这被认为是不好的做法。

标签: java


【解决方案1】:

Java 语言允许这样做是因为没有明确的、无可争议的理由来禁止它,特别是如果您认为在最初设计该语言时不一定知道当今的 Java 最佳实践。

请注意,调用抽象或非最终方法的构造函数确实有效,因为子类可以覆盖所述方法,并且因为构造函数可能正在子类的新创建实例上执行(由于子类的构造函数执行顺序到超类)。

据我所知,没有必要这样做。但肯定有一些第三方库会这样做,即使众所周知这是一种不好的做法。

【讨论】:

  • “构造函数可能正在一个新创建的子类实例上执行(由于构造函数从子类到超类的执行顺序)”——这正是不鼓励它的原因:你正在调用实例对象完全初始化之前的方法
  • 在我第一次学习 C++ 的那一天(在引入 Java 之前),关于预定义构造顺序(父->子)的争论是它避免了父构造函数调用虚拟的复杂性由于子状态还无效,因此对子应用的方法。所以在我看来,在最初的设计中至少对这个问题有所了解。
猜你喜欢
  • 2018-09-10
  • 2016-06-08
  • 2011-07-08
  • 1970-01-01
  • 2016-08-29
  • 2017-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多