【问题标题】:Is Java 100% object oriented? [closed]Java 是 100% 面向对象的吗? [关闭]
【发布时间】:2010-11-01 18:06:21
【问题描述】:

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

【问题讨论】:

  • 这是作业吗?对我来说,这听起来像是一个家庭作业问题。
  • 它有点 Gishu。 SO上有一个(非官方的?)家庭作业“政策”。例如,您应该以不同的方式回答家庭作业问题,例如没有给提问者一个完整的答案,而是更多指向正确方向的指针,有用的链接等等。
  • @Razzie - 与“SO 政策”相反,答案往往非常全面 - 请参阅本例中接受的答案。
  • 我不明白这个问题的意义。
  • 我愿意。发帖人可能在某处看到过“完全面向对象”这个词,想知道他最熟悉的 Java 语言是否是面向对象的。

标签: java oop


【解决方案1】:

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

“面向对象”对很多人来说也意味着很多事情。 您可以拥有基于类的 OO(C++、Java、C#),也可以拥有基于原型的 OO(Javascript、Lua)。

100% 面向对象并不意味着太多,真的。 Ruby 也有你会不时遇到的问题。

Java 让我困扰的是,它没有提供有效抽象思想的方法,也没有在存在问题的地方扩展语言。每当提出这个问题时(参见 Guy Steele 的“Growing a Language”),“哦,不,但是 Joe Sixpack 呢?”给出了论据。即使你设计了一种语言来防止自己的脚受伤,意外的复杂性和真正的复杂性之间还是有区别的(请参阅No Silver Bullet),平庸的开发人员总能找到创造性的方法来开枪。

例如 Perl 5 不是面向对象的,但它具有足够的可扩展性,它允许Moose,这是一个对象系统,它允许使用非常先进的技术来处理 OO 的复杂性。而syntactic sugar 也没问题。

【讨论】:

  • C#/.NET 表明无需放弃“面向对象类型”即可有效地实现“原语”。
  • @user2864740 但这也是后来的事,事后诸葛亮。
  • @TrippKinetics 我对此没有任何有用的非主观回应。
  • 是否有任何证据他们不想从一开始就使用原语?这样做真的是一种“妥协”吗?他们甚至考虑过在 Java 中将原语制作成一流的对象吗?
【解决方案2】:

根据Concepts in Programming Languages book,有一个叫做Ingalls 测试的东西,是由Smalltalk 小组的领导Dan Ingalls 提出的。那就是:

你能定义一种新的整数吗? 把你的新整数放入矩形 (它们已经是窗口的一部分 系统),要求系统拉黑 矩形,一切正常?

根据这本书,Smalltalk 再次通过了这个测试,但 C++ 和 Java 没有。不幸的是,这本书无法在线获得,但这里有一些支持slides(幻灯片 33 回答了您的问题)。

【讨论】:

    【解决方案3】:

    不,Java 不是,因为它具有与对象不同的原始数据类型(它们没有方法、实例变量等)。另一方面,Ruby 完全是 OOP。 一切都是一个对象。我可以这样做:

    1.class
    

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

    【讨论】:

    • Fixnum 并不是数字本身的同义词。大致来说,fixnum 是一个非 bignum 整数,即适合您机器的字长的整数。尝试 100000000.class1000000000000000000000000.class。造成这种区别的主要原因是,fixnum 可以放入您的堆栈中,而 bignum 很可能存在于您的堆中。
    • 在我的 64 位机器上,运行 MRI,[-2^62, 2^62) 中的所有整数都是固定数字。这个是正常的;通常,实现会保留前几位(在 MRI 的情况下为 2)用于“标记”单词的其余部分是否指定了一个固定编号,或者它是否是堆对象的地址,或者它是否是免费的等等。
    • 啊,是的,你是对的。我很抱歉没有注意细节:)
    【解决方案4】:

    Java 不是完全面向对象的。我认为 Smalltalk 和 Eiffel 是最流行的完全面向对象的语言。

    【讨论】:

      【解决方案5】:

      问题在于 面向对象 的定义并不明确,可能意味着很多事情。这篇文章更详细地解释了这个问题: http://www.paulgraham.com/reesoo.html

      此外,Alan Kay(Smalltalk 的发明者和“面向对象”一词的作者(?))曾说过他在考虑 OOP 时并没有想到 C++。所以我认为这也适用于 Java。

      完全面向对象的语言(无论这意味着什么)是可取的,因为它意味着更好的正交性,这是一件好事。但是考虑到 Java 在其他方面并不是非常正交的,它的 OO 不完整的一小部分在实践中可能并不重要。

      【讨论】:

        【解决方案6】:

        我会说完整的 OO 语言是那些将其元素(类、方法)作为对象访问的语言。

        从这个 POV 来看,Java 不是完全的 OOP 语言,而 JavaScript 是(不管它有原语)。

        【讨论】:

          【解决方案7】:

          不,因为它的数据类型不是对象(例如intbyte)。我相信 Smalltalk 是真正面向对象的,但我对这种语言只有一点经验(大约两个月,大约五年前)。

          我也听说过 Ruby 人群的说法,但我对这种语言的经验

          当然,这是使用“真正的 OO”的定义,意思是它只有对象,没有其他类型。其他人可能不同意这个定义。


          在对 Python 进行了一些研究之后(尽管我已经在其中编写了一年左右的代码,但我不知道名称/对象的区别——我猜我更傻了),它可能确实是真正的 OO。

          以下代码可以正常工作:

          #!/usr/bin/python
          i = 7
          print id(i)
          print type(i)
          print i.__str__()
          

          输出:

          6701648
          <type 'int'>
          7
          

          所以即使是基本整数也是这里的对象。

          【讨论】:

          • Ruby(和 Python)是纯面向对象的语言,其中所有元素都是对象。
          • @notnoop,我可以写 'i = 7;在 Python 中打印“你好”,我。很难相信那是真正的 OO。
          • Smalltalk / Sqeak 完全面向对象。
          • 您可以在 Python 中执行“True = False”,它确实改变了 True 的值。但我不能以同样的方式处理整数。在某人的代码中坚持大约 5 分钟可能会很有趣。
          • @donut,这可能是因为 True 是绑定到真实对象的名称。如果需要,您可以将其重新绑定到错误对象。不幸的是,您似乎无法将其与“True = True”绑定回来,尽管您可以执行“True = not True”来创建一个新的真实对象(该死的虐待狂)。
          【解决方案8】:

          “为什么java不将原始数据类型设计为对象方式?”

          在几年前的 Sun 开发者日,我记得 James Gosling 回答了这个问题。他说他们希望完全从原始对象中抽象出来——只留下标准对象,但后来时间用完了,决定用他们现有的东西发货。很伤心。

          【讨论】:

            【解决方案9】:

            Java 显然不是 100% OO。您可以轻松地以程序样式对其进行编程。大多数人都这样做。确实,库和容器往往不会容忍这种范式。

            【讨论】:

              【解决方案10】:

              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)float.plus(int) 一样返回float,等等。

              最终我认为原语的理由是效率:确定 int 对象可以纯粹作为 JVM 整数值处理所需的静态分析在设计语言时可能被认为是一个太大的问题。

              【讨论】:

                【解决方案11】:

                这是仅在学术意义上真正重要的问题之一。 Ruby 经过优化,可以尽可能将 int、long 等视为原语。 Java 只是明确地说明了这一点。如果 Java 有原语是对象,那么就会有 IntPrimitive、LongPrimitive 等(无论名称如何)类。如果没有特殊方法(例如没有 IntPrimitive.factorial),这很可能是最终的。这意味着在大多数情况下它们都是原始的。

                【讨论】:

                  【解决方案12】:

                  要实现真正的 100% OO,请以 Smalltalk 为例,其中 一切 都是一个对象,包括编译器本身,甚至 if 语句:ifTrue: 是发送到布尔值的消息带有代码块参数。

                  【讨论】:

                    【解决方案13】:

                    由于您提到的原因,Java 具有原语,并不能使其成为纯粹的面向对象的编程语言。但是,强制每个程序都是一个类,这使得它非常面向面向对象的编程。

                    正如你提到的,Ruby 也是我想到的第一个语言,它是一种没有原语的语言,所有值都是对象。这确实使它比 Java 更面向对象。另一方面,据我所知,并不要求一段代码必须与一个类相关联,就像 Java 的情况一样。

                    也就是说,Java 确实有包含 IntegerBooleanCharacter 等原语的对象。使用原语的原因可能是 Peter 的回答中给出的原因——在 90 年代中期引入 Java 时,系统上的内存大多为两位数兆字节,因此将每个值都作为对象是很大的开销.

                    (大,当然是相对的。我不记得确切的数字,但对象开销大约是 50-100 字节的内存。绝对超过原始值所需的几个字节的最小值)

                    如今,许多桌面拥有数 GB 内存,对象的开销已不再是问题。

                    【讨论】:

                    • 在 ruby​​ 中,当您在类之外声明方法或变量时,它会隐式添加到主对象内核中。将所有方法封装在类中并不会使其更 OO。
                    • @Alexandru Nedelcu:啊,谢谢您提供的信息 :) 而且,仅仅因为将代码包装在类中并不能使其面向对象,这也是事实。用面向对象的编程语言编写过程代码很容易。
                    • 但是,在 Ruby 中,方法本身是一个对象吗?
                    【解决方案14】:

                    那么我们可以将 java 视为 100% 对象吗 面向语言?

                    没有。

                    另一个问题:为什么 java 没有 将原始数据类型设计为对象 怎么办?

                    主要是出于性能原因,也可能是为了让来自 C++ 的人更熟悉。

                    【讨论】:

                      【解决方案15】:

                      Java 不是 100% OO。 Java 可能会走向 99% OO(想想自动装箱,Scala)。 我会说 Java 现在是 87% OO。

                      为什么 java 不设计原始数据 类型作为对象方式?

                      早在 90 年代就有性能原因,同时 Java 保持向后兼容。所以他们不能把它们拿出来。

                      【讨论】:

                      • 我很高兴听到你得到了确切的数字。
                      • 87%?让我想起了:dilbert.com/strips/comic/2008-05-08
                      • 但他们错了! Java 显然是 88.4% OO。
                      • 那个投反对票的扳机手指又痒了?我不明白为什么人们在没有给出解释的情况下投票低于零……
                      • 抱怨这个答案的人只是无知。 Sun Java 6u15 为 87.0% +/- 0.2% OO。
                      【解决方案16】:

                      没有。例如,Javascript 是。

                      那些 Integer、Long 和 Boolean 类会用什么写? 如果没有原始数组,您将如何编写 ArrayList 或 HashMap?

                      【讨论】:

                      • Ruby 将所有数据类型(原始和非原始)作为对象。仍然 ruby​​ 有 arraylist、hashmap 和数组。
                      • 它们是内置的;你不能让你自己的arraylist 像内置的一样高效。这是一个权衡。
                      • JavaScript 也有原语(数字、字符串、布尔值、null 和未定义)。
                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-06-16
                      • 2010-10-12
                      • 2010-09-08
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多