Arrays.sort()为什么不定义为接收一个Comparable[]数组?
众所周知,在Arrays.sort()方法中,有一个重载方法为:Arrays.sort(Object[] a)
。
这个方法要求Object[]数组中每一个元素都要实现Comparable
接口,即提供compareTo(Object other)
方法。一旦有某个元素没有实现该接口,将有可能抛出类型转换异常。
那么问题来了,为什么不强制要求传入一个Comparable[]
数组呢?这样的话不就能够保证数组中每个元素都实现Comparable接口了吗?
1. 从Java语言特性的角度分析
Java数组的类型不是由其元素类型决定的,而是由数组实例化时的类型决定的。也就是说,是在new Xxx[]
的时候决定的。
比如下面这个数组:
Object[]arr={
"hello","world"
};
它的实际类型就是Object[](大括号的简写法相当于Object[]arr=newObject[]{…};,因此其实例化类型为Object[])。虽然它里面的元素全部都是字符串,按照直觉你可能会觉得可以把它转换为String[]数组,但其实不然,下面的转换在运行时将会报错:
String[]arr2=(String[])arr;
注:如果反过来,将一个String[]数组转换为Object[]数组则是可行的,因为前者是后者的子类型。
所以这会导致什么问题?
如果Arrays.sort()声明为接收Comparable[]数组,那么就要求程序员在使用的时候必须一开始就为该数组实例化为一个Comparable[]数组或其兼容数组,而不能等到调用sort()方法的时候再临时转换,因为就像前面的例子那样,这种转换很有可能会失败(因为实例化的时候并未实例化成Comparable[]数组或其兼容数组)。
但肯定有人说:那一开始都声明成Comparable[]数组或其协变类型的数组不就可以了吗?这就会引起一种不便:即Java的部分API拿到就是Object[](比如Collection的toArray()方法),而即使你的Object[]内部对象的实际类型全部是Comparable兼容的,也不能把Object[]类型转换成Comparable[],因为Java认为它们类型不同,如果你调用某个API意外地得到了Object[]类型而又需要排序的话,你就得不得不复制一个新的Comparable[]数组出来排序,而这个是没有任何必要的,所以Java就这样设计API了。
参考资料:https://blog.csdn.net/laiyiqidashuangkou/article/details/105178651