java 参数化类型数组

        今天看java核心卷一,看到一个这样的局限性:“不能构建参数化类型的数组”。也就是不能构建泛型类型的数组,比如书上new Pair<String>[10]。

        原因就是数组存储时会考虑这个数组创建时的元素类型,如果不对会报错。不过这个过程是运行时才会出现的,所以如果只是编译那么是不会有问题的,所以书上说“能够通过数组存储的检查”

        可以看看字节码来验证这一点

     

public class Hello
{
  public static void main(String[] args) {
    var arr = new String[10];
    Object[] arr1 = arr;
    arr1[0] = new Object();
  }
}

这段对应的字节码如下

 明显没有检查类型,没有checkcast这一步骤。因为编译器看起来,arr1就是Object[]类型的,和String没关系。

        不过,如果真的运行起来会抛出一个ArrayStoreException,原因当然就是数组本身记住了自己是String[]类型的,但是却收到了一个Object类型。

        但是泛型就不一样了。因为JVM不知道泛型这个东西,他只知道原始类型,所以即使你传入的元素参数类型(例如Pair<String>和Pair<Integer>在JVM看起来是一样的)不一样它也检查不出来。看这个例子

public class Hello
{
  public static void main(String[] args) {
    var arr = (Pair<String>[]) new Pair<?>[10];
    Object[] arr1 = arr;
    arr1[0] = new Pair<Integer>(10, 10);
  }
}

        也是个书上的例子,这里arr就是个Pair<String>[]类型的数组,强转Object[]类型,当然没问题,然后给arr1[0]赋值Pair<Integer>类型实例,显然JVM看不出问题,因为对JVM来说,这就是个Pair[]类型的数组,然后你给第0个元素赋了一个Pair类型的实例。当然没问题。

        所以说这是不安全的,因为JVM不知道什么参数类型,所以Pair<String>和Pair<Integer>就是一个东西,传给数组也不会报错。

        但是,这和不是数组的情况是有区别的,例如这个

public class Hello
{
  public static void main(String[] args) {
    var p1 = new Pair<String>("123", "123");
    Pair<Integer> p2 = p1;
  }
}

        就会报错,编译都通不过。这个原因最开始就说了,是判断类型的过程不同,这里这个是编译器处理的,编译器是知道参数类型这个概念的,所以Pair<String>和Pair<Integer>是两个东西,编译觉得不行,你这不能转,所以就报错;但是数组的存储类型是在运行时由JVM检查的,对上面那个(第二个,arr和arr1那个)例子,编译器觉得arr1是个Object类型的数组,所以你给他传Pair<Integer>没问题,然后JVM觉得你这数组是个Pair类型的数组,所以传个Pair类型的元素,也没问题,所以参数类型这个东西编译器和JVM都没注意到,所以说不安全。

        不过,如果你在命令行编译,还是会有一个小注解的,这样子

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值