为什么不将java.lang.Object类声明为抽象类?
当然,对于一个有用的对象,它需要添加状态或行为,对象类是一个抽象,因此它应该被声明为抽象的…他们为什么不选择?
- 如果在.NET中已经决定了这一点,那么这是否可以不仅仅是一次嫖娼?你真的觉得Java会有不同的理由吗?嗯,我还是会回答的。
- Bill K:我想要实际的推理,因为它属于Java。我不在乎.NET。一个理由也不错,但我还是看不到。
- .NET的推理(或者至少是C)是C语言最初是Java的直接复制,所以他们只是用Java做了同样的操作。
- 为什么要将对象声明为抽象对象?有时,您需要一个类型无关紧要的占位符对象,该对象可以完美地工作。为什么要强迫人们为了这个目的而建立自己的班级?
即使没有特定的状态或行为,也会使用。
One example would be its use a s a generic guard that's used for symporanization:
1 2 3 4 5 6 7 8 9
| public class Example {
private final Object o = new Object();
public void doSomething () {
synchronized (o ) {
// do possibly dangerous stuff
}
}
} |
当这一类别在其实施中是一个简单的比特(这不明显是为什么它需要有一个解释性的目标,你可以宣布方法synchronized)时,有几种实际使用的例子。
- 如果类中有3个方法声明为synchronized,则所有3个方法只有一个锁,因此只能同时调用这3个方法中的1个。如果方法中有同步块,则可以使用多个对象作为锁。
- 至少在JavaUTI.Curror之前,或者除非你被困在Java 1.4中。
- 如果对象是抽象的,为什么不使用扩展对象的锁呢?
- @安德:是的,反正有些事情会这样做。例如,java.awt.component有"static class awttrelock"和"static final object lock=new awttrelock();"
- 从严格的OO观点来看,你很可能是对的,没有理由让任何对象从对象继承。对象类由于实际原因而存在,比如Java的类型系统的顶部;您自己的设计甚至不需要每个对象从一个基类继承。
- @andri:我将使用metamethods这个术语来描述对象内的方法的用途,因为它们在您用"对象"创建的系统之外是有用的。我认为当你允许对象被实例化时,你就进入了"奇怪循环"的领域。
- 安德:在1天之前做了很多事情,基本上是很差的实践,很可能是由于时间限制和缺乏对Java中最佳实践的认识(不难从那时起就犯错误):
- @托福:我有点希望在1.0上工作的人会贴"哎呀"的帖子。哈哈。
- "奇怪的循环"当你允许对象被实例化时?呵呵?你在说什么?
- @埃迪:看过道格拉斯·霍夫施塔特的《戈德尔、埃舍尔和巴赫》吗?
- @安德:是的,我只是不明白你在这里的意思。似乎是一个伟大的壮举。
- @埃迪:我们可以继续兜圈子,但最终这将证明我的观点,而不是你的观点。P
安德,我认为你是在以一种不必要的抽象程度来接近这一点——不是有意的。我认为这(imho)不必要的抽象级别是导致这里的"问题"的原因。您可能是从数学理论的方法来实现这一点的,我们中的许多人都是从"试图解决问题的程序员"的方法来实现这一点的。我认为这种方法上的差异导致了分歧。
当程序员看到实用性和如何实际实现某些东西时,有很多次您需要一些完全任意的对象,而这些对象的实际实例完全不相关。它不能为空。我在对另一篇文章的评论中给出的例子是*Set(*==Hash或Concurrent或选择类型的实现,这通常是通过使用支持*Map并使用Map键作为集合来完成的。您通常不能使用null作为Map值,因此通常使用静态Object实例作为值,这将被忽略并且永远不会使用。但是,需要一些非空的占位符。
另一个常见的用法是使用synchronized关键字,其中需要一些Object来同步打开,并且您希望确保同步项是完全私有的,以避免在不同类无意间在同一锁上同步时出现死锁。一个非常常见的习惯用法是分配一个private final Object在类中用作锁。公平地说,对于Java 5和EDCOX1(12)和相关的添加,这个习惯用法是不太适用的。
从历史上讲,在EDCOX1中,8是非常实例化的。您可以指出,在设计上进行小的更改或API进行小的更改时,这将不再是必需的。你可能是对的。
是的,API可以提供一个扩展Object的Placeholder类,而不添加任何内容,作为上述用途的占位符。但是——如果扩展Object,但不添加任何内容,那么类中除了允许Object是抽象的之外还有什么值?从数学上讲,理论上讲,也许人们可以找到一个值,但从实用主义上讲,这样做会增加什么值?
在编程中,有时您需要一个对象,一些对象,任何不为空的具体对象,一些可以通过==和/或.equals()进行比较的对象,但是您不需要任何其他特性。它的存在只是作为一个唯一的标识符,否则什么也不做。Object完全满足了这个角色,而且(imho)非常干净。
我想这就是为什么Object没有被声明为抽象的部分原因:它直接对不被声明是有用的。
- +1,最佳答案。
- 我相信一个可实例化的对象允许程序员把OOP理解为一种建模技术时出现惯用的失败。如果它是一个bug,它现在被用作一个特征,如果它不被允许,原本更好的方法现在对Java来说是习惯用法。
- +因为尽管我们可能不同意,但我还是同意迈耶斯的观点。P
- @安德:我完全同意,如果是对象抽象的,在API中只有几个小的更改就足以完全替换一个可实例化的对象。如果是我,我会删除Java中的每个对象也是一个锁,需要锁(或导数)来进行同步。
对象特异性的方法是,类别必须扩展,以便于使用?不,所以不需要抽象。
一个类别作为抽象的概念有一个很好的定义,它不适用于对象。
- 因此,您的"因此"在逻辑上并不遵循前面的语句,而抽象类的概念具有适用于对象的定义良好的含义。
- @安德:你觉得怎么样?如其他人所示,对象本身是有用的。你如何理解它必然是抽象的?
- @ande:abstract表示一个类,它的定义不完整,无法创建该类的实例。这显然不适用于对象,即使创建实例没有用处。其他人也指出了一些有用的案例。
- @克里斯:一个抽象应该定义一个抽象;一个对象应该被声明为抽象的,因为你试图概念化的现实世界环境不能实例化没有潜力的不可替代的物质。
您可以安装同步锁定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Object lock = new Object();
void someMethod () {
//safe stuff
synchronized(lock ) {
//some code avoiding race condition
}
}
void someOtherMethod () {
//safe code
synchronized(lock ) {
//some other stuff avoiding race condition
}
} |
比零更大的进攻目标是什么?
这是一个很好的位置标记(好像没有任何东西)。
我也不认为这是一个好的设计,如果没有一个抽象的方法需要去做一个抽象的对象。
我不是说没有什么是最好的东西,自从吃了面包以后——我在"发明家"的杂志上读了一篇文章我甚至不认为任何东西都是虚构的!我猜有人可能会在某个地方提出他发明的零。。。。。。。。
- 在某些意义上,非抽象对象的实例化是空值的实例化,但更糟的是,因为我看到了使用它的参数。它是一个没有物质和能力的东西,事实上,也许它可以用来代表暗物质,嗯。
- 我已经看到,当现有的对象实例没有意义时,它使用了很多简单的锁。为什么这么强调你可能是个更好的问题…在每种语言中都有如此多的异常问题。
- "我想有人会说他发明了零。"零的概念实际上是被发明的。来自维基百科:"零作为一个数字的概念,而不仅仅是一个分离的符号,归因于印度,到9世纪,在那里,CE使用零进行了实际计算。"
- @ande:对象不是空值。它是一个零维点,是你能实例化的最小可能的东西。这与空值非常不同。当能够实例化对象显然非常有用时,为什么会让对象被实例化而困扰?
- @Eddie:列出的使用并不排除它们被应用于任何其他实例化的对象扩展。
我不确定这是原因,但它允许(或允许,如今有更好的方式完成这项任务),以供作为锁定的对象使用:
ZZU1
你永远不知道什么时候你可能想用一个简单的对象作为安慰剂。把它当作一个数字系统中的一个零(而不为这个工作,因为没有数据)。
- 不过,也有一些原语需要计算。为什么要将对象的概念拖到不值得使用的情况下?
- 在Veluy开始,Java没有原语(不是我认为这个讨论很重要)。
- @安德:阿兰·丹尼尔斯不是在说数数。他说的是使用占位符。原始人不会做这项工作,因为,嗯,他们是原始人。
- @艾迪:什么样的人?确切地?数字、值、符号?
- @ande,set(=some type of set)的一个(通用)实现是使用map,并将一个对象作为值,使用键作为集。您必须将*某物作为一个值,因此,对象。占位符。有些地方不能使用空值,但必须使用某些任意对象。占位符。
- @埃迪:你可以使用一个抽象来指定一个你想保留位置的对象类型。然后用扩展该抽象类的任何对象替换它。
像往常一样,guava提供帮助:http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/optional.html这里的内容可用于从代码中删除"非空占位符"的空值/对象实例。
这里有完全独立的问题:
- 为什么不把物体抽象化?
- 如果他们决定在将来的版本中将灾难抽象化,那么灾难会发生多少呢?
应该有理由将类抽象化。一种是防止客户机实例化类,并强制他们只使用子类(无论出于什么原因)。另一种是,如果您希望通过提供抽象方法将其用作接口,则子类必须实现抽象方法。也许,Java的设计者没有看到这样的原因,所以EDCX1〔22〕仍然是具体的。