Arrays.sort函数在以下场景中抛出ClassCastException:
public static void main(String[] args) {
Object[] obj = {
new String("string"),
new Integer(10)
};
Arrays.sort(obj);
}
我希望这里有一个例外,错误信息显示:
线程中的异常" main" java.lang.ClassCastException: java.lang.String无法强制转换为java.lang.Integer at java.lang.Integer.compareTo(Integer.java:52)at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290) 在java.util.ComparableTimSort.sort(ComparableTimSort.java:157)at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)at java.util.Arrays.sort(Arrays.java:472)
sort()函数是否试图将数组中的第一个值转换为第二个值?
我将Object数组中的元素反转为:
Object[] obj = {
new Integer(10),
new String("string")
};
现在Exception说Integer不能转换为String:
线程中的异常" main" java.lang.ClassCastException: java.lang.Integer无法强制转换为java.lang.String java.lang.String.compareTo(String.java:108)at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290) 在java.util.ComparableTimSort.sort(ComparableTimSort.java:157)at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)at java.util.Arrays.sort(Arrays.java:472)
我知道在这种情况下排序是不可能的,但内部究竟发生了什么?
答案 0 :(得分:4)
Arrays.sort
使用Comparable
接口对元素进行排序。您可以这样想:每个元素都将被转换为Comparable
对象,并且将调用方法compareTo
。问题是整数将compareTo
方法实现为compareTo(Integer i)
,而String
使用compareTo(String s)
。因此,当调用String
的{{1}}方法时,java会尝试将Integer
投射到compareTo
,从而产生Integer
。
答案 1 :(得分:2)
http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort(java.lang.Object[])
按照升序对指定的对象数组进行排序 它的元素的自然顺序。数组中的所有元素 必须实现Comparable接口。此外,所有元素 数组必须是相互可比的(即e1.compareTo(e2)必须 不为任何元素e1和e2抛出ClassCastException 数组)。
为了对字符串和整数进行排序,您必须能够以两种方向进行转换。它只是在第一个ClassCastException失败,根据如何声明数组,它恰好是不同的。
每次获得不同的异常这一事实只是实现定义。
答案 2 :(得分:2)
要使Arrays#sort(Object[])
生效,其中的元素必须彼此Comparable
。以此类为例
public class Example implements Comparable<Example>{
@Override
public int compareTo(Example o) {
return 0;
}
}
编译时,编译器会添加一个合成方法(下面的第二个方法),其中显式转换为extends Comparable<HERE>
声明中使用的任何类型参数
public int compareTo(Example);
descriptor: (LExample;)I
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: iconst_0
1: ireturn
LineNumberTable:
line 6: 0
public int compareTo(java.lang.Object);
descriptor: (Ljava/lang/Object;)I
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: checkcast #2 // class Example
5: invokevirtual #3 // Method compareTo:(LExample;)I
8: ireturn
LineNumberTable:
line 1: 0
为了保持类型安全,这是必要的。当sort
开始比较元素时,它只有Object
(Comparable
)引用。所以它确实
comparableRef.compareTo(otherComparableRef);
在内部,会进行强制转换,以便您可以安全正确地比较类型。
答案 3 :(得分:1)
字面意思来自the docs:
抛出:
ClassCastException
- 如果数组包含不可相互比较的元素(例如,字符串和整数)
当我们在java.util.ComparableTimSort.Java:232
查看来源时,我们可以看到这种情况发生:
if (pivot.compareTo(a[mid]) < 0)
将我们带到Comparable
界面的文档:
抛出:
ClassCastException
- 如果指定的对象类型阻止将其与此对象进行比较。
Stacktrace来到这里:
Arrays.sort() -> Arrays.java:468
ComparableTimSort.sort() -> Arrays.java:472
sort() -> ComparableTimSort.java:145
sort() -> ComparableTimSort.java:149
binarySort() -> ComparableTimSort.java:213
compareTo() -> ComparableTimSort.java:232
答案 4 :(得分:0)
调用Arrays#sort
方法将评估您作为条目提供的Array
,并通过 sort 算法,它将在每个方法上调用Comparable#comapareTo
方法Object
。当您切换对象顺序时,这种比较以两种方式进行将导致不同的异常跟踪。
Here您可以查看java.util.Arrays#sort
方法。