Citron__ 2018-06-16 08:51 采纳率: 33.3%
浏览 1200
已结题

有关可变参数与泛型结合,泛型数组的问题。

可能不应该在这种问题上死磕,但是还是想不明白:
代码来自《Effective Java》 第三版,32章
贴代码:

static <T> T[] toArray(T... args) {
    return args;
}

static <T> T[] pickTwo(T a, T b, T c) {
    switch(ThreadLocalRandom.current().nextInt(3)) {
      case 0: return toArray(a, b);
      case 1: return toArray(a, c);
      case 2: return toArray(b, c);
    }
    throw new AssertionError(); // Can't get here
}

public static void main(String[] args) {
    String[] attributes = pickTwo("Good", "Fast", "Cheap");
}

程序能够顺利通过编译,但是运行会报错。
报错原因为:pickTwo返回的类型为Objcet[]类型,因此无法强制转换为String[] 类型。

但是:

Objcet[] obj=new String[1]();
String[] str=(String[])obj;

是能正确运行的。

按照擦除和编译的语法糖,代码应该被编译成这样:

public static void main(String[] args) {
    String[] attributes = pickTwo("Good", "Fast", "Cheap");
}

static  String[] pickTwo(Object a, Object b, Object c) {
    switch(ThreadLocalRandom.current().nextInt(3)) {
      case 0: return (String[])toArray(a, b);
      case 1: return (String[])toArray(a, c);
      case 2: return (String[])toArray(b, c);
    }
    throw new AssertionError(); // Can't get here
}

static  String[] toArray(Object... args) {
    return (String[])args;
}

这也是泛型出现的意义。
可是
static <T> T[] pickTwo(T a, T b, T c) {
pickTwo明明根据传入类型告诉了编译器,需要返回T[]类型。
因此传入String类型的代码不应该就返回String[]
可是书上和运行结果确实证明了pickTwo方法确实始终返回了Objcet类型。

这是因为泛型数组的特殊性么?是在想不通,望指点

  • 写回答

2条回答 默认 最新

  • ggbbbbbbbbbbb 2018-06-16 09:02
    关注

    因为java是不允许创建泛型数组的啊。。。先假设Java可以创建泛型数组,由于java泛型的类型擦除和数组的协变。下面的代码将会编译通过。

    List[] stringLists=new List[1];

    List intList = Arrays.asList(40);

    Object[] objects = stringLists;

    objects[0]=intList;

    String s=stringLists[0].get(0);

     由于泛型的类型擦除,List<Integer>,List<String>与List在运行期并没有区别,所以List<String>放入List<Integer>并不会产生ArrayStoreException异常。但是String s=stringLists[0].get(0);将会抛出ClassCastException异常。如果允许创建泛型数组,就绕过了泛型的编译时的类型检查,将List<Integer>放入List<String>[],并在实际存的是Integer的对象转为String时抛出异常。
    
    如果泛型没有限制类型。比如List s=new ArrayList[5];或者List<?>[] s=new ArrayList[5];还是可以使用的,应为没有了编译时的类型检查,需要开发者自己保证类型转换安全。
    
    评论

报告相同问题?

悬赏问题

  • ¥20 matlab计算中误差
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊