Java是否是100%的面向对象编程语言?

12

Java有原始数据类型,不像Ruby一样从对象派生。那么我们可以认为Java是一个100%面向对象的语言吗?还有一个问题:为什么Java没有以对象的方式设计原始数据类型?


4
这是一份作业吗?听起来像是一道作业问题。 - Scott Wisniewski
1
它有点像Gishu。在SO上有一个(非官方的?)家庭作业“政策”。例如,您应该以不同的方式回答家庭作业问题,例如不给出完整答案,而是给出正确方向的指针、有用的链接等等。 - Razzie
@Razzie - 答案往往非常全面,与'SO政策'相反 - 在这种情况下请参阅被接受的答案。 - Gishu
Razzie所提到的作业“政策”是指当人们仅仅要求为他们编写代码时(而不是针对这个问题),应该遵循的规定。在这些给我代码的情况下,提示、指针和链接更加合适。 - basszero
5
我不明白这个问题的意义。 - Cheeso
13
我明白了。海报上可能看到过“完全面向对象”的术语,想知道Java是否是面向对象的语言,也许这是他最熟悉的语言。 - zoul
16个回答

30

当Java首次出现(版本1.x)时,JVM非常非常慢。不将基本类型实现为一等对象是他们为了速度而做出的妥协,尽管我认为从长远来看这是一个非常糟糕的决定。

“面向对象”对于不同的人意味着很多不同的事情。你可以有基于类的面向对象(C ++,Java,C#),或者你可以有基于原型的面向对象(Javascript,Lua)。

100%的面向对象并没有多大意义。Ruby也有问题,你会时不时遇到一些问题。

让我困扰的是Java没有提供有效抽象思想、在语言上解决问题的手段。每当有人提出这个问题时(参见Guy Steele的“Growing a Language”),都会被以“哦,不,乔六包怎么办?”的论点回击。即使你设计一种不会让自己踩到坑里的语言,意外的复杂性和真正的复杂性之间有区别(参见No Silver Bullet),平庸的开发人员总会找到创造性的方式来给自己挖坑。

例如,Perl 5不是面向对象的,但它具有足够的可扩展性,可以允许一个名为Moose的对象系统,以处理面向对象的复杂性。而语法糖也不是问题。


Java的原始类型是一等公民吗? - Filip Bartuzi
C#/.NET表明,实现“基本类型”并不需要放弃“面向对象类型”。 - user2864740
但那也是后来才出现的,有了事后的好处。 - Tripp Kinetics
@TrippKinetics,我对此没有任何有用的非主观性回应。 - user2864740
他们最初不想使用基元素,有没有任何证据?这样做实际上是一种“妥协”,他们真的这样做了吗?他们是否曾经考虑过将基元素作为Java中的一级对象? - user207421

19
不行,因为它具有不是对象的数据类型(例如intbyte)。我认为Smalltalk是真正的面向对象语言,但我只有一点点使用那种语言的经验(大约五年前两个月左右)。
我也听说过Ruby的支持者声称这一点,但我对这种语言完全没有经验。
当然,这是使用“真正的OO”定义,意味着它只有对象没有其他类型。其他人可能不同意这个定义。
经过一些关于Python的研究后(尽管我在其中编码了一年左右,但我对名称/对象区分毫不知情 - 我更加愚蠢,我猜),看起来它可能确实是真正的面向对象语言。
以下代码可以正常工作:
#!/usr/bin/python
i = 7
print id(i)
print type(i)
print i.__str__()

输出:

6701648
<type 'int'>
7

所以即使是基础整数在这里也是对象。


1
Ruby(和Python)是纯面向对象的语言,其中所有元素都是对象。 - notnoop
1
@notnoop,我可以在Python中编写“i = 7; print“ hello”,i”。很难相信这是真正的面向对象。 - paxdiablo
1
4 = 2:语法错误:无法分配给文字。- 尝试规避语言的好努力,但我相信Guido不会那么愚蠢 :-) - paxdiablo
2
在Python中,您可以执行“True = False”,它确实会更改True的值。但是我无法以同样的方式操纵整数。将其插入某人的代码大约5分钟可能会有点有趣。 - donut
3
@donut,这很可能是因为True是绑定到一个真对象的名称。如果你想,你可以将其重新绑定到假对象。不幸的是,你似乎无法通过'True = True'重新绑定它,但是你可以使用'True = not True'来创建一个新的真对象(该死的虐待狂)。 - paxdiablo
显示剩余10条评论

14
为了实现真正的100%面向对象编程,可以参考Smalltalk语言。在这种语言中,所有都是对象,包括编译器本身,甚至if语句: ifTrue:是发送给布尔值的一个带有代码参数的消息。

6
问题在于“面向对象”没有很好的定义,可以有很多不同的含义。本文详细解释了这个问题:http://www.paulgraham.com/reesoo.html 另外,Smalltalk的发明人Alan Kay曾经说过,“面向对象”的概念在他脑海中并没有涉及到C++。因此,我认为这也适用于Java。
让语言完全成为面向对象的(无论那意味着什么)是值得期望的,因为它可以提高正交性,这是一件好事。但考虑到Java在其他方面已经不太正交了,其面向对象的不完整可能实际上并不重要。

5
不,Java不是完全面向对象的,因为它有原始数据类型,这些类型与对象不同(它们没有方法、实例变量等)。另一方面,Ruby是完全面向对象的。 所有东西都是对象。我可以这样做:
1.class

它会返回1的类(Fixnum,基本上是一个数字)。在Java中无法做到这一点。


Fixnum并不是与数字本身完全同义的。Fixnum大致上是一个非Bignum整数,即适合于您机器的字长大小的整数。尝试100000000.class1000000000000000000000000.class。区分的主要原因是Fixnum可以适应您的堆栈,而Bignum则很可能存在于您的堆中。 - C. K. Young
在我的64位机器上,运行MRI时,范围在[-2^62, 2^62)内的所有整数都是fixnums。这是正常的;通常实现会保留顶部几个位(在MRI的情况下为2)来“标记”其余的字是否指定了fixnum,或者它是一个堆对象的地址,或者它是空闲的等等。 - C. K. Young
啊,是的,你说得对。我没有注意到细节,对此感到抱歉 :) - Saurabh Sharan

5

Java 不是100%面向对象的。Java 可能会朝着99%面向对象的方向发展(考虑自动装箱、Scala)。我认为现在 Java 已经是87%面向对象的。

为什么 Java 没有将原始数据类型设计成对象方式?

在上个世纪90年代,由于性能原因以及需要保持向后兼容性,他们无法将它们拿出来变成对象。


2
很高兴听到您得到了确切的数字。 - Matthew Flaschen
5
87%?让我想起了这个漫画:http://dilbert.com/strips/comic/2008-05-08/ - Razzie
3
他们是错误的!Java 明显是 88.4% 的面向对象。 - anon
1
好的,这87%缺少幽默标签。生活中很少有事情是(或可能是)100%的。性能:记得在97年Win95 64Mb RAM上运行我的第一个Applets,现在想到所有原语都生活在堆上,也许GC永远不会让Applets的代码运行 :-) - PeterMmm
2
抱怨这个答案的人只是无知。Sun Java 6u15 是87.0% +/- 0.2% 的面向对象。 - Tom Hawtin - tackline
显示剩余6条评论

3

正如你所提到的,Java具有原始类型,这并不使它成为一种纯面向对象的编程语言。然而,要求每个程序都是一个类使其非常面向对象。

正如你提到的那样,Ruby是我想到的第一种语言,它没有原始类型,所有值都是对象。这确实使它比Java更加面向对象。另一方面,据我所知,并没有像Java那样需要将代码片段与类关联的要求。

话虽如此,Java确实有包装原始类型的对象,例如IntegerBooleanCharacter等。有原始类型的原因可能就是Peter回答中给出的原因——在90年代中期引入Java时,系统上的内存大多数只有两位数兆字节,因此每个值都是一个对象的开销很大。

(当然,"大"是相对的。我记不清确切的数字,但一个对象的开销大约是50-100字节的内存。明显比原始值所需的几个字节多)

如今,许多桌面计算机都拥有多个千兆字节的内存,对象的开销已经不再是问题。


1
在 Ruby 中,当你在类外声明一个方法或变量时,它会被隐式添加到 Kernel,即主对象中。 将所有方法都封装在类中并不能使其更加面向对象。 - Alexandru Nedelcu
@Alexandru Nedelcu: 啊,谢谢你的信息 :) 而且,仅仅将代码放入类中并不意味着它是面向对象的。在面向对象编程语言中编写过程式代码是很容易的。 - coobird
但是,在 Ruby 中,方法本身是一个对象吗? - Tripp Kinetics

2

为什么Java没有用对象方式设计原始数据类型?

我记得在几年前的Sun开发者大会上,James Gosling回答了这个问题。他说他们本来想完全抽象出原始数据类型 - 只留下标准对象,但后来时间不够了,只能决定使用已有的内容进行发布。非常遗憾。


1

Java不能显然取消非对象原语(int等)的一个原因是它不支持本地数据成员。 想象一下:

class int extends object
{
    // need some data member here.  but what type?
    public native int();
    public native int plus(int x);
    // several more non-mutating methods
};

重新考虑后,我们知道Java会为每个对象维护内部数据(锁等)。也许我们可以定义一个没有数据成员但具有本地方法来操作这些内部数据的class int

剩余问题:常量--但这些可以类似于字符串处理。运算符只是语法糖,+将在编译时映射到plus方法,尽管我们需要小心确保int.plus(float)返回floatfloat.plus(int)也是如此,以此类推。

最终,我认为原始类型的正当理由是效率:当设计语言时,需要进行静态分析以确定int对象可以纯粹地作为JVM整数值处理,这可能被认为是一个过大的问题。


1

我认为全面面向对象的编程语言是那些可以将其元素(类、方法)作为对象进行操作的语言。

从这个角度来看,Java不是完全的面向对象语言,而JavaScript是(无论它是否有原始类型)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接