为啥 Java 中的每个对象都隐式扩展 java.lang.Object 类?
Posted
技术标签:
【中文标题】为啥 Java 中的每个对象都隐式扩展 java.lang.Object 类?【英文标题】:Why does every object in Java implicitly extend java.lang.Object class?为什么 Java 中的每个对象都隐式扩展 java.lang.Object 类? 【发布时间】:2013-10-07 13:01:33 【问题描述】:我用 Java 编程已经有一段时间了,但是当我试图向朋友解释 java.lang.Object
类是什么时,我想不出比简单的单行词更多的东西:
Java 中的所有对象都隐式扩展
java.lang.Object
我不太清楚为什么要这样做。
于是,我查看了GrepCode上的源码,希望能找到一些线索。现在我知道java.lang.Object
是什么以及它的作用,我想知道是否有任何具体原因说明它为何如此设计。
我的问题仍然存在:为什么每个对象都应该扩展 java.lang.Object
?
【问题讨论】:
这样您就可以自信地在任何对象上调用 Object 方法。 一开始我很困惑,但您实际上是在问为什么 Java 具有单根类层次结构吗? (与允许事物从其他根类继承相反) 每个对象都是一个Object
,因为拥有所有对象共有的功能很有用。
我投票关闭是因为您的 “为什么每个对象都应该扩展它?” 不清楚。对象上有方法,每个对象都可以使用方法。所以答案很明显,一定有什么让你担心,而且还不清楚。
那么,它只是一个设计决策,还有其他的吗?
【参考方案1】:
Java 中的每个类都是 Object 类的后代(直接或间接)。 Object 类定义了所有对象必须具有的基本状态和行为,例如将自己与另一个对象进行比较、转换为字符串、等待条件变量、通知其他对象条件变量已更改的能力,并返回对象的类。
【讨论】:
【参考方案2】:引用Head first Java 2nd edition:
如果 Java 中没有通用的超类,就没有办法 让 Java 的开发人员创建具有方法的类,这些方法可以 采用您的自定义类型...他们在编写时不知道的类型 ArrayList 类。
这从本质上解释了 Java 中对通用预定义类类型的需求,它可用于实现该语言提供的不同功能。
【讨论】:
【参考方案3】:我会说原因是为 java 中的所有对象提供一个通用 API 以支持基本功能,例如
同步 -wait
, notify
, notifyAll
垃圾收集 - finalize
收藏支持 - hashCode
, equals
对象克隆 - clone
每个对象
有一个属于它的类 -getClass
可以将自己表示为一个字符串,因为我们是
人类并且可以读取字符串 - toString
【讨论】:
【参考方案4】:这就是语言的设计方式。每个对象都将从基类Object
继承。这意味着它保证每个对象都会有某些方法,例如toString()
、equals()
、hashCode()
等。
【讨论】:
【参考方案5】:每个类都隐式地扩展了 Object 类,因此它们提供了根据 Java 推荐每个类都应具有的基本功能。如clone()、equals()、hashCode()、toString()等
隐式意味着如果你不扩展任何类,那么只有编译器会隐式扩展 Object 类。但是如果类已经扩展了其他类,那么编译器将不会扩展 Object 类。例如。 A类
B 类扩展 A
这里编译器会在A类声明中隐式添加extends Object类。
A 类扩展对象
B 类扩展 A
由于A类扩展了Object类,因此它将提供Object类的基本功能,例如equals()、toString()等。由于 B 类扩展了 A 类,A 类隐含地扩展了 Object 类,所以 B 类也提供了所有这些特性。
因此,通过遵循这种方法,每个类对象(变量)都符合每个 Java 对象应该具有的特性,而不是 Java 不允许的多重继承(一个扩展多个类的类)。这种方法遵循多级继承。
【讨论】:
我也相信Object类的扩展默认强制“多重继承”是不可能的。【参考方案6】:我认为Object
最重要的用途不是提供像toString()
这样的通用方法,而是提供一个通用的type,可以容纳所有引用类型。
C++ 没有 Object
等价物,人们仍然很高兴。但由于 Java 没有指针和类 C++ 模板,因此需要 Object
才能实现 Collection
s 等。
另请参阅关于引用和原始类型的讨论。
【讨论】:
【参考方案7】:我会说Design
。每个Object
都应该支持的通用/强制方法写在那里并将该类扩展为语言规范。
您可以在Official Docs 中找到原因。
如果我们说这是一个Object
,它们必须有共同的方法,由API
定义/决定。
想象一下您自己的每个课程的以下方法。
protected Object clone() throws CloneNotSupportedException
Creates and returns a copy of this object.
public boolean equals(Object obj)
Indicates whether some other object is "equal to" this one.
protected void finalize() throws Throwable
Called by the garbage collector on an object when garbage
collection determines that there are no more references to the object
public final Class getClass()
Returns the runtime class of an object.
public int hashCode()
Returns a hash code value for the object.
public String toString()
Returns a string representation of the object.
Object 的 notify、notifyAll 和 wait 方法都在同步程序中独立运行的线程的活动中发挥作用:
public final void notify()
public final void notifyAll()
public final void wait()
public final void wait(long timeout)
public final void wait(long timeout, int nanos)
所以为了减轻痛苦,创建了一个通用且标准的API
。
【讨论】:
可以说,clone
应该属于“神奇的”CloneableObject
基类,而finalize
应该被替换为“注册清理通知”方法。但是,使用通用函数来找出对象的类并定义等价关系是有帮助的[如果对象具有单独的一对相等/hashCode 方法,它们一致地定义了两个通用等价关系,而不是使用一个,那么后者会更有帮助。一对方法,但对于它实现的关系不一致]。【参考方案8】:
这样做是因为 toString() 等大多数基本函数将被自动继承,而对于您的下一个问题,这是 NOT 多重继承,它是 multilevel 继承... 在多重继承中,单个类派生自 2 个或更多基类,而在多级中,正如您所说,它有一个基类,该基类本身派生自 Object 类
【讨论】:
【参考方案9】:对象类是java编程的最超类,它有根据类型预定义的方法,你可以使用这些方法。 & 你不再需要扩展对象类&它隐式存在的任何地方
【讨论】:
没有说为什么。这不是一个真正的问题。【参考方案10】:这是一个 java 设计决定。它使用了继承和可重用性的概念。这样可以确保所有类都有一些基本方法,例如wait()
、toString()
等。
【讨论】:
【参考方案11】:见docs:
java.lang 包中的 Object 类位于 类层次树。每个班级都是直接或间接的后代, 对象类的。您使用或编写的每个类都继承 Object 的实例方法。您不需要使用任何这些方法, 但是,如果您选择这样做,您可能需要用代码覆盖它们 这是特定于您的班级的。
Object
类简单地定义了所有对象必须具有的基本状态 - 就像将其与其他对象进行比较一样。
它是所有事物的 parent 类。它只是为所有派生对象提供一种模板。
【讨论】:
是的,但是 OP 询问 为什么以上是关于为啥 Java 中的每个对象都隐式扩展 java.lang.Object 类?的主要内容,如果未能解决你的问题,请参考以下文章