Java的Arrays.asList()违反了面向对象编程原则吗?

3

在Java中,我想把一个数组转换成一个列表。既然Java是一种面向对象的语言,我期望可以像下面这样做:

int[] myArray = { 1, 2, 3 };               // non-working code
List myList = myArray.toList();

当我发现 array 对象没有 toList 方法时,感到惊讶。实现我想要的功能的正确方法是:

int[] myArray = { 1, 2, 3 };               // working Java code
List myList = Arrays.asList(myArray);

起初我想知道int[]是否不被认为是一个对象,但我可以调用clone()等方法,所以我确定它是一个对象。
为什么Java的设计者使用了第二种方法(静态方法与OOP不一致),而不是第一种方法(基于对象的OOP原则)?
我注意到C ++也会使用第二种方法,我认为这是从C语言遗留下来的负担。但在C#中,有一个ToList()方法。 Arrays.asList()只是抵制向OOP演进的一种方式,还是有一些潜在的理论支持这种做法?

1
它并没有“破坏面向对象编程”,只是设计不良。 - Dave Newton
嗯,我认为在面向对象编程语言中设计不良意味着它违反了面向对象编程的原则。那么,你同意这是一个糟糕的设计吗? - chessofnerd
1
我以为那就是我说的。但我不同意你的论点。 - Dave Newton
我们不知道Java设计师为什么这样做。你必须去问他们。在这里,你只会得到或多或少有根据的意见和猜测。而且,“与OOP不一致”本身就是主观的,在没有普遍接受的定义的情况下。例如,一些支持者可能会否认Java是一种OOP语言。但我并不这样认为,我只是觉得整个争论毫无意义。 - user207421
4个回答

3

数组并没有你期望的所有方法,它所拥有的方法都是从Object继承而来的,通常是无用的。

int[] array = { 1, 2, 3 };
int[] array2 = { 1, 2, 3 };
System.out.println(array.equals(array2)); // prints false
System.out.println(array.hashCode() == array2.hashCode()); // prints false
System.out.println(array.toString()); // prints something like [I@a2634feg

我曾试图让Sun/Oracle来解决这个问题,但我得到的消息是,要彻底解决它会非常复杂。


所以回答这个问题,Java的处理方式确实违反了面向对象编程(OOP)的原则吗? - chessofnerd

3

int[]是一个对象。

然而,面向对象编程并不要求对象提供所有接受它作为参数的工厂方法。


1
转换方法不在你期望的位置。而且没有真正的技术原因。如果你看一下Scala(它使用相同的虚拟机,字节码是兼容的):
object ArrayListDemo {
  def main(args: Array[String]) {
    val list = args.toList
    val array = list.toArray

    println("= List =")
    println(list)
    println(list.mkString(", "))
    println(list.size)
    println(list.length)

    println("= Array =")
    println(array)
    println(array.mkString(", "))
    println(array.size)
    println(array.length)
  }
}

这将给你这个结果(如果用两个参数Helloworld调用):

= 列表 =
List(Hello, world)
Hello, world
2
2
= 数组 =
[Ljava.lang.String;@15663a2
Hello, world
2
2

你可以看到它确实是一个“JVM数组”,带有额外的方法。所有集合类型(丰富和原始)都有转换方法。
所以,是的,它感觉不像面向对象编程 - 它感觉“命令式”。

1

Java从第一个版本(JDK1.0)开始就有数组(int[], Foo[])。当时对于数据结构的支持非常少,你需要自己完成所有操作。在V1.2中引入了ListArrayListArrayshttp://docs.oracle.com/javase/6/ocs/api/java/util/List.html)。可能当时无法更改语言或过于复杂。

我是Java早期的密切观察者(通过Sun联系)。我记得Java 1.0相当基础,图形界面(AWT 1.02)是在最后一刻编写的。据我回忆,Java被设计为面向对象,但最初的范围有限(它被吹嘘为一种新的动画语言,但Java AWT 1.02非常受限)。规范中仍然存在来自那个时期的痕迹。

Java在当时的巨大贡献是WriteOnceRunAnywhere (WORA)(最初为WriteOnceDebugEverywhere!),我认为这是早期开发人员和维护者的主要考虑因素。Java受C++启发,并带有一些构造体(例如,int,double作为原语 - autoboxing稍后作为一个补救措施)。C#能够从Java开始(而不是C++),在某些方面是Java应该的修订版。所有语言都有一些负担,每个新语言都会摆脱一些。

这似乎证实了我怀疑的事情。他们一开始就走错了路,无法恢复。我不明白为什么他们不能添加一个 toArray() 方法,并让其实现返回 Arrays.asList()。也许是为了避免多种方式做同一件事情??? - chessofnerd
有没有一种机制可以让Java的数组ToList()方法返回一个正确的泛型类型,假设String[].ToList()应该产生一个ArrayList<String>,但是如果它起作用的话,int[].ToList()将不得不产生一个ArrayList<Integer> - supercat

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