Arrays.sort抛出类强制转换异常

时间:2014-08-13 15:40:17

标签: java arrays sorting casting

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)

我知道在这种情况下排序是不可能的,但内部究竟发生了什么?

5 个答案:

答案 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开始比较元素时,它只有ObjectComparable)引用。所以它确实

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方法。