加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java泛型何时在运行时使用转换?

发布时间:2020-12-14 05:31:10 所属栏目:Java 来源:网络整理
导读:我正在阅读有关C模板和C#泛型的讨论,以及它们与 Java类型擦除泛型的不同之处.我读了一条声明说Java仍然在运行时使用转换,例如在处理集合时.如果这是真的,我不知道它! 假设我有以下代码: ArrayListSomeClass list = new ArrayListSomeClass();...SomeClass
我正在阅读有关C模板和C#泛型的讨论,以及它们与 Java类型擦除泛型的不同之处.我读了一条声明说Java仍然在运行时使用转换,例如在处理集合时.如果这是真的,我不知道它!

假设我有以下代码:

ArrayList<SomeClass> list = new ArrayList<SomeClass>();
...
SomeClass object = list.get(0);

我的问题是.这是否有效编译

ArrayList list = new ArrayList();
...
SomeClass object = (SomeClass) list.get(0);

如果是这样,为什么?我认为列表的类型是ArrayList< SomeClass>在编译时和运行时保证只有SomeClass存储在ArrayList中?或者你可以做不安全的类型转换来转换ArrayList< OtherClass>到ArrayList< SomeClass>?

是否有其他场合在Java泛型中进行运行时类型转换?

最后,如果确实使用了在运行时进行的转换,那么JIT是否可以忽略运行时转换检查?

(请不要回答/评论微观优化是不值得的,先发制人的优化是万恶之源等等.我在其他类似的问题上看到了这些.这些点很好理解,但它们并没有带走尝试点了解如何在引擎盖下实现类型擦除的泛型.)

解决方法

这是我写的一个简短的程序:
public class Test<T> {

  public T contents;

  public Test(T item) {
    contents = item;
  }

  public static void main(String[] args) {

    Test<String> t = new Test<String>("hello");
    System.out.println(t.contents);

  }

}

尝试用javac编译它,然后用javap -verbose查看字节码.我选择了几条有趣的线条:

public java.lang.Object contents;

这应该在Test构造函数的定义之前出现.在示例代码中,它是T类型,现在它是一个Object.这是擦除.

现在,看一下主要方法:

public static void main(java.lang.String[]);
Code:
   Stack=3,Locals=2,Args_size=1
   0:   new #3; //class Test
   3:   dup
   4:   ldc #4; //String hello
   6:   invokespecial   #5; //Method "<init>":(Ljava/lang/Object;)V
   9:   astore_1
   10:  getstatic   #6; //Field java/lang/System.out:Ljava/io/PrintStream;
   13:  aload_1
   14:  getfield    #2; //Field contents:Ljava/lang/Object;
   17:  checkcast   #7; //class java/lang/String
   20:  invokevirtual   #8; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   23:  return

然后我们可以在第17行看到checkcast命令,就在println之前 – 这是Java从Object转换为擦除的泛型类型的字符串 – String

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读