Discuss / Java / 对泛型可变参数的理解

对泛型可变参数的理解

Topic source

呱呱

#1 Created at ... [Delete] [Delete and Lock User]

泛型是通过类型擦除来实现的,而可变参数只是一个传递数组变量的语法糖,本质上还是创建一个数组然后传入。

所以泛型可变参数实际上就是 Object 数组,这样代码就可以等价为

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        String[] ss = new String[]{"one", "two", "three"};
        String[] arr = (String[]) asArray(ss); // asArray 返回的就是 ss 只不过声明为 Object[],实际上还是 String[]
        System.out.println(Arrays.toString(arr));
        // ClassCastException:
        String[] firstTwo = (String[]) pickTwo("one", "two", "three"); // pickTwo 返回的是一个新创建的 Object[],只不过里面的元素实际上是字符串
        System.out.println(Arrays.toString(firstTwo));
    }

    static Object[] pickTwo(Object k1, Object k2, Object k3) {
        Object[] objs = new Object[]{k1, k2};
        return asArray(objs);
    }

    /**
     * asArray 本质上没有做任何处理,只是把传入的数据返回了而已。
     */
    static Object[] asArray(Object[] objs) {
        return objs;
    }
}

👉菌👈

#2 Created at ... [Delete] [Delete and Lock User]

我把上述代码化简到最核心的部分,以便理解。
之所以出现这种区别在于:一个跟随了原来的数组,而另一个新建了数组。虽然他们的元素都一样,但是仍然会在 (String []) 强转时被区别对待,这也是异常的来源。

class Test {
    //这一段会编译成功    
    Object[] olds = (String[]) oldArray(new String[]{""});
    static Object[] oldArray(Object[] objs) {
        return objs;
    }

    //抛出 ClassCastException    
    Object[] news = (String[]) newArray("");
    static Object[] newArray(Object obj) {
        return new Object[]{obj};
    }
}

QQ少年

#3 Created at ... [Delete] [Delete and Lock User]

代码简化之后实际上就是

public class Main {
    public static void main(String[] args) {
        String[] arr = (String[]) (Object[]) new String[]{"one", "two", "three"};;

        // ClassCastException:
        String[] firstTwo = (String[]) new Object[]{"one", "two", "three"};
    }
}

可以很明显看出,会将 Object[] 转型为 String[] 导致异常。


  • 1

Reply