当Comparator不为null时,Arrays.sort(T[], Comparator)是否会抛出ClassCastException?
Arrays.sort(T[], Comparator<? super T>)的ClassCastException触发场景分析
问题背景
Java 20标准库java.util.Arrays的sort(T[] a, Comparator<? super T> c)方法Javadoc说明:该方法会根据指定Comparator对数组排序,要求所有元素可通过该Comparator相互比较(即c.compare(e1,e2)不会抛出ClassCastException),若元素无法比较则抛出该异常。
这里存在疑问:当传入的Comparator实例c不为null时,编译器的泛型类型系统是否已保证数组元素可通过c相互比较,不会触发ClassCastException?
类型擦除视角的分析
该方法经类型擦除后的签名为static void sort(Object[] a, Comparator c)。假设c的静态类型是Comparator<Number>,它的compare方法会将参数转换为Number类型,这个转换成功的前提是数组元素的运行时类型为Number或其子类,而这依赖于数组的运行时类型是Number[]或其子类。
从方法泛型签名来看,? super T的约束能保证数组静态类型符合要求(比如当? super T为Number时,T是Number或其子类)。如果数组运行时类型不符合要求,会在进入sort方法之前就抛出ClassCastException,而非方法内部抛出。
测试验证结果
编写测试案例验证后发现:
- 仅当传入
null作为Comparator时,sort方法本身才会抛出ClassCastException; - 其他看似抛出该异常的场景,实际都是进入
sort方法前的数组类型转换异常; - 传入静态类型不符的数组会直接触发编译错误。
核心疑问
- 是否只有传入
null作为Comparator时,Arrays.sort(T[], Comparator)才会抛出ClassCastException? - 是否存在无需编译器unchecked警告且
c不为null的场景,导致该方法抛出该异常?
测试代码
package org.example.basics.generics.arrays; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.util.Arrays; import java.util.Comparator; class ArraysTest { private static final Comparator<Number> compareAsWholeNumber = new Comparator<Number>() { @Override public int compare(java.lang.Number o1, java.lang.Number o2) { return Long.compare(o1.longValue(), o2.longValue()); } }; @Test public void sortingIntsThrowsNoException() { Integer[] ints = new Integer[]{4, 2, 3}; Assertions.assertDoesNotThrow(() -> { Arrays.sort(ints, compareAsWholeNumber); }); } @Test public void sortingDoublesThrowsNoException() { Double[] doubles = new Double[]{4.0, 2.0, 3.0}; Assertions.assertDoesNotThrow(() -> { Arrays.sort(doubles, compareAsWholeNumber); }); } @Test public void sortingNumbersThrowsNoException() { Number[] numbers = new Number[]{4.0, 2, 3.0f}; Assertions.assertDoesNotThrow(() -> { Arrays.sort(numbers, compareAsWholeNumber); }); } // @Test // public void sortingObjectsIsCompileError() { // Object[] numbers = new Number[]{4.0, 2, 3.0f}; // Arrays.sort(numbers, compareAsWholeNumber); // } @Test public void sortingDisguisedStringsThrowsClassCastException() { Throwable e = Assertions.assertThrows(ClassCastException.class, () -> { Arrays.sort((Number[]) new Object[]{"4.0", "2", "3.0f"}, compareAsWholeNumber); }); e.printStackTrace(); } @Test public void sortingDisguisedStringsThrowsClassCastExceptionAtArrayAssignment() { Assertions.assertThrows(ClassCastException.class, () -> { Number[] numbers = (Number[]) new Object[]{"4.0", "2", "3.0f"}; }); } @Test public void sortingNonComparableWithNullComparatorThrowsClassCastException() { Number[] numbers = new Number[]{4.0, 2, 3.0f}; Throwable e = Assertions.assertThrows(ClassCastException.class, () -> { Arrays.sort(numbers, null); }); e.printStackTrace(); } }
内容的提问来源于stack exchange,提问作者GreyBit
相关产品推荐
相关产品推荐

