为什么 java.lang.Object 不是抽象的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2117689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why java.lang.Object is not abstract?
提问by Elister
Possible Duplicate:
Java: Rationale of the Object class not being declared abstract
Why is the Object class, which is base class of 'em all in Java, not abstract?
为什么 Object 类是 Java 中所有它们的基类,而不是抽象类?
I've had this question for a really really long time and it is asked here purely out of curiosity, that's all. Nothing in my code or anybody's code is breaking because it is not abstract, but I was wondering why they made it concrete?
我有这个问题已经很长时间了,在这里问这个问题纯粹是出于好奇,仅此而已。我的代码或任何人的代码都没有破坏,因为它不是抽象的,但我想知道他们为什么把它具体化?
Why would anyone want an "instance" (and not its presence a.k.a. Reference) of this Object class? One case is a poor synchronization code which uses the instance of an Object for locking (at least I used it this way once.. my bad).
为什么有人想要这个 Object 类的“实例”(而不是它的存在,又名参考)?一种情况是糟糕的同步代码,它使用对象的实例进行锁定(至少我曾经这样使用过一次……我的错)。
Is there any practical use of an "instance" of an Object class? And how does its instantiation fit in OOP? What would have happened if they had marked it abstract (of course after providing implementations to its methods)?
Object 类的“实例”有什么实际用途吗?它的实例化如何适应 OOP?如果他们将其标记为抽象(当然是在为其方法提供实现之后)会发生什么?
采纳答案by Grundlefleck
Without the designers of java.lang.Objecttelling us, we have to base our answers on opinion. There's a few questions which can be asked which may help clear it up.
在没有设计师java.lang.Object告诉我们的情况下,我们必须根据意见来回答。有几个问题可以问,这可能有助于澄清问题。
Would any of the methods of Object benefit from being abstract?
Object 的任何方法都会从抽象中受益吗?
It could be argued that some of the methods would benefit from this. Take hashCode()and equals()for instance, there would probably have been a lot less frustration around the complexities of these two if they had both been made abstract. This would require developers to figure out how they should be implementing them, making it more obvious that they should be consistent (see Effective Java). However, I'm more of the opinion that hashCode(), equals()and clone()belong on separate, opt-in abstractions (i.e. interfaces). The other methods, wait(), notify(), finalize(), etc. are sufficiently complicated and/or are native, so it's best they're already implemented, and would not benefit from being abstracted.
可以争辩说,某些方法将从中受益。以hashCode()和equals()举例来说,有可能早就少了很多挫折围绕这两个的复杂性,如果他们俩都已经取得抽象。这将要求开发人员弄清楚他们应该如何实现它们,使它们应该保持一致更加明显(参见 Effective Java)。但是,我更倾向于认为hashCode(),equals()并且clone()属于单独的选择加入的抽象(即接口)。其他方法 、wait()、notify()、finalize()等非常复杂和/或本机,因此最好它们已经实现,并且不会从抽象中受益。
So I'd guess the answer would be no, none of the methods of Object would benefit from being abstract.
所以我猜答案是否定的,Object 的任何方法都不会从抽象中受益。
Would it be a benefit to mark the Object class as abstract?
将 Object 类标记为抽象是否有好处?
Assuming all the methods are implemented, the only effect of marking Object abstract is that it cannot be constructed (i.e. new Object()is a compile error). Would this have a benefit? I'm of the opinion that the term "object" is itself abstract (can you find anything around you which can be totally described as "an object"?), so it would fit with the object-oriented paradigm. It is however, on the puristside. It could be argued that forcing developers to pick a name for any concrete subclass, even empty ones, will result in code which better expresses their intent. I think, to be totally correctin terms of the paradigm, Object should be marked abstract, but when it comes down to it, there's no real benefit, it's a matter of design preference (pragmatism vs. purity).
假设所有的方法都实现了,标记Object abstract的唯一效果就是不能构造(即new Object()编译错误)。这会有好处吗?我认为术语“对象”本身是抽象的(你能在你周围找到任何可以完全描述为“对象”的东西吗?),所以它适合面向对象的范式。然而,它是纯粹主义的一面。有人可能会争辩说,强迫开发人员为任何具体的子类选择一个名称,即使是空的,也会导致代码更好地表达他们的意图。我认为,在范式方面完全正确,应该标记 Object abstract,但归根结底,没有真正的好处,这是设计偏好的问题(实用主义与实用主义)。
Is the practice of using a plain Object for synchronisation a good enough reason for it to be concrete?
使用普通对象进行同步的做法是否足以让它变得具体?
Many of the other answers talk about constructing a plain object to use in the synchronized()operation. While this may have been a common and accepted practice, I don't believe it would be a good enough reason to prevent Object being abstract if the designers wanted it to be. Other answers have mentioned how we would have to declare a single, empty subclass of Object any time we wanted to synchronise on a certain object, but this doesn't stand up - an empty subclass could have been provided in the SDK (java.lang.Lockor whatever), which could be constructed any time we wanted to synchronise. Doing this would have the added benefit of creating a stronger statement of intent.
许多其他答案都谈到构建一个在synchronized()操作中使用的普通对象。虽然这可能是一种普遍且被接受的做法,但我认为如果设计者希望它是抽象的,我认为这不是阻止 Object 抽象的充分理由。其他答案提到了在任何时候我们想要在某个对象上同步时,我们必须如何声明一个空的 Object 子类,但这站不住脚 - SDK 中可能已经提供了一个空子类(java.lang.Lock或其他) ,可以在我们想要同步的任何时候构建。这样做会有一个额外的好处,即创建更强大的意图声明。
Are there any other factors which could have been adversely affected by making Object abstract?
是否有任何其他因素可能因使 Object 抽象而受到不利影响?
There are several areas, separate from a pure design standpoint, which may have influenced the choice. Unfortunately, I do not know enough about them to expand on them. However, it would not suprise me if any of these had an impact on the decision:
从纯设计的角度来看,有几个方面可能会影响选择。不幸的是,我对它们的了解还不够深入。但是,如果其中任何一个对决定产生影响,我也不会感到惊讶:
- Performance
- Security
- Simplicity of implementation of the JVM
- 表现
- 安全
- JVM 实现的简单性
Could there be other reasons?
会不会是其他原因?
It's been mentioned that it may be in relation to reflection. However, reflection was introduced after Object was designed. So whether it affects reflection or not is moot - it's not the reason. The same for generics.
有人提到它可能与反射有关。但是,反射是在设计 Object 之后引入的。所以它是否影响反射是没有实际意义的 - 这不是原因。泛型也是如此。
There's also the unforgettable point that java.lang.Object was designed by humans: they may have made a mistake, they may not have considered the question. There is no language without flaws, and this maybe one of them, but if it is, it's hardly a big one. And I think I can safely say, without lack of ambition, that I'm very unlikely to be involved in designing a key part of such a widely used technology, especially one that's lasted 15(?) years and still going strong, so this shouldn't be considered a criticism.
还有一个令人难忘的一点,java.lang.Object 是由人类设计的:他们可能犯了一个错误,他们可能没有考虑过这个问题。没有没有缺陷的语言,这可能是其中之一,但如果是,那也算不上什么。我想我可以有把握地说,不缺乏雄心壮志,我不太可能参与设计如此广泛使用的技术的关键部分,尤其是持续了 15(?)年并且仍然很强大的技术,所以这个不应被视为批评。
Having said that, I would have made it abstract ;-p
话虽如此,我会把它抽象化;-p
Summary
Basically, as far as I see it, the answer to both questions "Why is java.lang.Object concrete?" or (if it were so) "Why is java.lang.Object abstract?" is... "Why not?".
总结
基本上,在我看来,这两个问题的答案“为什么 java.lang.Object 是具体的?” 或者(如果是的话)“为什么 java.lang.Object 是抽象的?” 是……“为什么不呢?”。
回答by Wim Hollebrandse
Plain instances of java.lang.Objectare typically used in locking/syncronization scenarios and that's accepted practice.
的普通实例java.lang.Object通常用于锁定/同步场景,这是公认的做法。
Also - what would be the reason for it to be abstract? Because it's not fully functional in its own right as an instance? Could it really do with some abstract members? Don't think so. So the argument for making it abstract in the first place is non-existent. So it isn't.
另外 - 它抽象的原因是什么?因为作为一个实例,它本身并没有完全发挥作用?它真的可以与一些抽象成员一起使用吗?不要这么认为。因此,首先将其抽象化的论点是不存在的。所以不是。
Take the classic hierarchy of animals, where you have an abstract class Animal, the reasoning to make the Animalclass abstract is because an instance of Animal is effectively an 'invalid' -by lack of a better word- animal (even if all its methods provide a base implementation). With Object, that is simply not the case. There is no overwhelming case to make it abstract in the first place.
以动物的经典层次结构为例,在那里你有一个抽象类Animal,使Animal类抽象的原因是因为 Animal 的实例实际上是“无效的”——因为缺乏更好的词——动物(即使它的所有方法都提供了一个基本实现)。对于Object,情况并非如此。首先,没有压倒性的例子使它抽象。
回答by Brett Daniel
I can think of several cases where instances of Objectare useful:
我可以想到几种Object有用的实例:
- Locking and synchronization, like you and other commenters mention. It is probably a code smell, but I have seen Object instances used this way all the time.
- As Null Objects, because
equalswill always return false, except on the instance itself. - In test code, especially when testing collection classes. Sometimes it's easiest to fill a collection or array with dummy objects rather than
nulls. - As the base instance for anonymous classes. For example:
Object o = new Object() {...code here...}
- 锁定和同步,就像您和其他评论者提到的那样。这可能是一种代码异味,但我已经看到 Object 实例一直以这种方式使用。
- 作为Null Objects,因为
equals将始终返回 false,除了实例本身。 - 在测试代码中,尤其是在测试集合类时。有时用虚拟对象而不是
nulls填充集合或数组是最容易的。 - 作为匿名类的基实例。例如:
Object o = new Object() {...code here...}
回答by BlueRaja - Danny Pflughoeft
From everything I've read, it seems that Objectdoes not need to be concrete, and in fact shouldhave been abstract.
从我读过的所有内容来看,似乎Object不需要具体,实际上应该是抽象的。
Not only is there no need for it to be concrete, but after some more readingI am convinced that Objectnotbeing abstract is in conflict with the basic inheritance model - we should not be allowing abstract subclasses of a concrete class, since subclasses should only addfunctionality.
Clearly this is not the case in Java, where we have abstract subclasses of Object.
不仅不需要它是具体的,而且经过更多阅读之后,我确信Object不抽象与基本继承模型相冲突 - 我们不应该允许具体类的抽象子类,因为子类应该只添加功能。
显然,在 Java 中情况并非如此,我们有Object.
回答by ishmeister
I think it probably should have been declared abstract, but once it is done and released it is very hard to undo without causing a lot of pain - see Java Language Spec 13.4.1:
我认为它可能应该被声明为抽象的,但是一旦完成并发布,就很难在不引起很多痛苦的情况下撤消 - 请参阅 Java 语言规范 13.4.1:
"If a class that was not abstract is changed to be declared abstract, then preexisting binaries that attempt to create new instances of that class will throw either an InstantiationError at link time, or (if a reflective method is used) an InstantiationException at run time; such a change is therefore not recommended for widely distributed classes."
“如果一个非抽象类被更改为抽象类,那么试图创建该类的新实例的预先存在的二进制文件将在链接时抛出一个 InstantiationError,或者(如果使用了反射方法)在运行时抛出一个 InstantiationException ;因此,不建议对广泛分布的类进行这种更改。”
回答by Itay Maman
From time to time you need a plain Object that has no state of its own. Although such objects seem useless at first sight, they still have utility since each one has different identity. Tnis is useful in several scenarios, most important of which is locking: You want to coordinate two threads. In Java you do that by using an object that will be used as a lock. The object need not have any state its mere existence is enough for it to become a lock:
有时您需要一个没有自己状态的普通对象。虽然这些物品乍一看似乎没什么用,但它们仍然有用,因为每个人都有不同的身份。Tnis 在几个场景中很有用,其中最重要的是锁定:您想要协调两个线程。在 Java 中,您通过使用将用作锁的对象来实现。对象不需要任何状态,它的存在就足以使它成为一个锁:
class MyThread extends Thread {
private Object lock;
public MyThread(Object l) { lock = l; }
public void run() {
doSomething();
synchronized(lock) {
doSomethingElse();
}
}
}
Object lock = new Object();
new MyThread(lock).start();
new MyThread(lock).start();
In this example we used a lock to prevent the two threads from concurrently executing doSomethingElse()
在这个例子中我们使用了一个锁来防止两个线程并发执行 doSomethingElse()
If Object were abstract and we needed a lock we'd have to subclass it without adding any method nor fields just so that we can instantiate lock.
如果 Object 是抽象的并且我们需要一个锁,我们就必须在不添加任何方法或字段的情况下对它进行子类化,以便我们可以实例化锁。
Coming to think about it, here's a dual question to yours: Suppose Object were abstract, will it define any abstract methods? I guess the answer is No. In such circumstances there is not much value to defining the class as abstract.
考虑一下,这里有一个双重问题要问你:假设 Object 是抽象的,它会定义任何抽象方法吗?我想答案是否定的。在这种情况下,将类定义为抽象类并没有多大价值。
回答by josefx
I don't understand why most seem to believe that making a fully functional class, which implements all of its methods in a use full way abstract would be a good idea.
I would rather ask why make it abstract? Does it do something it shouldn't? is it missing some functionality it should have? Both those questions can be answered with no, it is a fully working class on its own, making it abstract just leads to people implementing empty classes.
我不明白为什么大多数人似乎认为制作一个功能齐全的类,以完全抽象的方式实现其所有方法是一个好主意。
我宁愿问为什么要抽象?它做了不该做的事吗?它是否缺少一些它应该具备的功能?这两个问题的答案都不是,它本身就是一个完全工作的类,使其抽象只会导致人们实现空类。
public class UseableObject extends AbstractObject{}
UseableObject inherits from abstract Object and surprise it can be implemented, it does not add any functionality and its only reason to exist is to allow access to the methods exposed by Object.
Also I have to disagree with the use in "poor" synchronisation. Using private Objects to synchronize access is safer than using synchronize(this) and safer as well as easier to use than the Lock classes from java util concurrent.
UseableObject 继承自抽象 Object 并且令人惊讶的是它可以实现,它没有添加任何功能,它存在的唯一原因是允许访问 Object 公开的方法。
此外,我不得不不同意在“差”同步中的使用。使用私有对象来同步访问比使用同步(this)更安全,并且比 java util concurrent 中的 Lock 类更安全也更容易使用。
回答by Jay
Seems to me there's a simple question of practicality here. Making a class abstract takes away the programmer's ability to do something, namely, to instantiate it. There is nothing you can do with an abstract class that you cannot do with a concrete class. (Well, you can declare abstract functions in it, but in this case we have no need to have abstract functions.) So by making it concrete, you make it more flexible.
在我看来,这里有一个简单的实用性问题。使类抽象会剥夺程序员做某事的能力,即实例化它。抽象类没有什么是具体类做不到的。(好吧,您可以在其中声明抽象函数,但在这种情况下,我们不需要抽象函数。)因此,通过使其具体化,可以使其更加灵活。
Of course if there was some active harm that was done by making it concrete, that "flexibility" would be a drawback. But I can't think of any active harm done by making Object instantiable. (Is "instantiable" a word? Whatever.) We could debate whether any given use that someone has made of a raw Object instance is a good idea. But even if you could convince me that every use that I have ever seen of a raw Object instance was a bad idea, that still wouldn't prove that there might not be good uses out there. So if it doesn't hurt anything, and it might help, even if we can't think of a way that it would actually help at the moment, why prohibit it?
当然,如果通过将其具体化而造成了一些积极的伤害,那么这种“灵活性”将是一个缺点。但是我想不出让 Object 可实例化会造成任何积极的伤害。(“可实例化”是一个词吗?无论如何。)我们可以争论某人对原始 Object 实例的任何给定用途是否是一个好主意。但是,即使您可以说服我,我所见过的原始 Object 实例的每次使用都是一个坏主意,这仍然不能证明那里可能没有好的用途。因此,如果它没有任何伤害,并且可能会有所帮助,即使我们目前无法想到它实际上会有所帮助的方法,为什么要禁止它?
回答by Yishai
I think all of the answers so far forget what it was like with Java 1.0. In Java 1.0, you could not make an anonymous class, so if you just wanted an object for some purpose (synchronization or a null placeholder) you would have to go declare a class for that purpose, and then a whole bunch of code would have these extra classes for this purpose. Much more straight forward to just allow direct instantiation of Object.
我认为到目前为止所有的答案都忘记了 Java 1.0 是什么样的。在 Java 1.0 中,你不能创建一个匿名类,所以如果你只是为了某个目的(同步或空占位符)想要一个对象,你必须为此目的声明一个类,然后一大堆代码就会有这些额外的类用于此目的。更直接地只允许直接实例化 Object。
Sure, if you were designing Java today you might say that everyone should do:
当然,如果您今天正在设计 Java,您可能会说每个人都应该这样做:
Object NULL_OBJECT = new Object(){};
But that was not an option in 1.0.
但这不是 1.0 中的一个选项。
回答by Pool
I suspect the designers did not know in which way people may use an Object may be used in the future, and therefore didn't want to limit programmers by enforcing them to create an additional class where not necessary, eg for things like mutexes, keys etc.
我怀疑设计者不知道将来人们可能以何种方式使用对象,因此不想通过强制他们创建一个额外的类来限制程序员在不必要的地方,例如互斥锁、键等等等。

