【问题标题】:difference between referencing a parameterized type instance to its raw type and using a raw type to reference another raw type instance?将参数化类型实例引用到其原始类型和使用原始类型引用另一个原始类型实例之间的区别?
【发布时间】:2018-11-09 22:36:52
【问题描述】:

我最近开始从基础开始学习 Java,我遇到了这个问题 关于泛型类型的“小”误解,它提出了如下问题:

将参数化类型实例引用到其原始类型和 使用原始类型引用另一个原始类型实例?

我的意思是,这就是这个sn-p的区别:

ArrayList rawTypeList_NoRawInstance = new ArrayList</*Any type here*/>();

还有这个:

ArrayList rawTypeList_RawInstance = new ArrayList();

代码:

import java.util.*;


public class TestGenerics{

   public static void main(String args[]){


          ArrayList rawTypeList_RawInstance = new ArrayList();
          ArrayList rawTypeList_NoRawInstance = new ArrayList<Integer>();  /* instead of Integer could be placed any kind of type, this 
                                                                            * is just an example */

          rawTypeList_RawInstance.add("example RawInstance");      // warning launched
          rawTypeList_NoRawInstance.add("example NoRawInstance");  // same warning here

          System.out.println(rawTypeList_RawInstance.get(0));      // content showed without errors/warning
          System.out.println(rawTypeList_NoRawInstance.get(0));    // same here

          String exampleRawInstance1    = (String)rawTypeList_RawInstance.get(0);   // raw type instance compiled without error 
          String exampleNoRawInstance1  = (String)rawTypeList_NoRawInstance.get(0); //  Generic type -Integer- instance compiled without error 

          Integer exampleRawInstance2   = (Integer)rawTypeList_RawInstance.get(0);      // ClassCastException as expected
          Integer exampleNoRawInstance2 = (Integer)rawTypeList_NoRawInstance.get(0);    // same here, logically
   }

}

谁能解释一下其中的区别并举一些例子说明可能的不同后果?

【问题讨论】:

    标签: java generics type-erasure raw-types


    【解决方案1】:

    泛型仅在编译时存在,它们将被编译器删除(这称为类型擦除)。它们用于向编译器提供一些类型信息。这可以帮助您避免类型转换(与 Java 1.5 之前一样)并允许编译器进行更多类型检查。对于程序员来说,这也是一个有价值的信息,例如,如果您在接口中看到泛型类型。

    没有泛型:

    ArrayList list = new ArrayList();
    

    所以,如果你写的话会有所不同:

    ArrayList</*Any type here*/> list = new ArrayList<>();
    

    现在编译器知道list中的对象类型。

    但是这个对没有泛型的版本没有真正的影响:

    ArrayList list = new ArrayList</*Any type here*/>();
    

    变量列表没有泛型信息,所以和没有泛型的版本一样好(或差)。

    【讨论】:

    • 是的,我明白了。@Donat 事实上,Java 编译器应该提供类型转换,如 Oracle 文档中类型擦除部分所述。 “在必要时插入类型转换以保持类型安全”来源:docs.oracle.com/javase/tutorial/java/generics/erasure.html 那么,这意味着只有引用/变量“列表”可以移植到编译器的这种类型转换上?所以,在这种情况下:'ArrayList list = new ArrayList*Any type here*/>();'一个实例,另一方面不能?因为否则它应该在指向的对象上提供类型安全
    • 是的,泛型类型信息附加到变量中,并且仅在编译时存在。该实例在运行时存在,然后类型信息已被删除。
    猜你喜欢
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    • 2011-06-29
    • 2021-10-27
    • 1970-01-01
    相关资源
    最近更新 更多