当前位置: 首页 > 知识库问答 >
问题:

Java类型擦除和数组

华安民
2023-03-14

OracleDoc说泛型是在java中使用调用类型擦除的技术实现的,这就是它的工作原理。

  1. 如果类型参数是无界的,则用其边界或对象替换泛型类型中的所有类型参数。因此,生成的字节码只包含普通类、接口和方法

所以,如果我有一个通用类说容器如下:

class Container<T>{
T initialValue;
List<T> valueList=new ArrayList<T>();
public List<T> getValueList(){
  return valueList;
}

}

通过类型擦除处理后,它的等效类将如下所示:

class Container{
    Object initialValue;
    List valueList=new ArrayList();
    public List getValueList(){
      return valueList;
    }

    }

如果这里有错误,请纠正我

类似地,如果a修改上述类,如下所示

class Container<T>{
    T initialValue;
    List<T> valueList=new ArrayList<T>();
    T[] arrayValue;
    public Container(T[] array){
       arrayValue=array;
     }
    public List<T> getValueList(){
      return valueList;
    }

    }

这不会相当于???

class Container{
    Object initialValue;
    List valueList=new ArrayList();
    Object[] arrayValue;
    public Container(Object[] array){
       arrayValue=array;
     }
    public List getValueList(){
      return valueList;
    }

    }

如果这是真的,那么我也应该有这样的:T[]arrayValue=new T[10];//编译时间错误;因为上面的语句会被转换成

Object[] arrayValue=new Object[10];

需要了解Java中数组的类型擦除工作原理吗??

共有1个答案

勾俊
2023-03-14

不能创建泛型数组。原因是数组早于Java的泛型,并且数组不使用类型擦除。因此,例如,整数[]String[]在运行时确实具有不同的类型。如果你写new T[]编译器不知道它需要创建什么样的数组。

您可以通过执行以下操作来创建假通用数组:

T[] array = (T[]) new Object[10];

但是您必须记住,您确实创建了一个对象数组,而不是T数组。在运行时,可以将非T实例放入其中,因此只有当数组是类的私有字段且从未传递给其他对象时,才可以这样做,以便您可以精确控制将哪些对象放入数组中。

如果你有一个

T[] array = (T[]) Array.newInstance(typeToken, 10); 

 类似资料:
  • 问题内容: 我以为Java擦除会在编译时消除泛型类型,但是当我自己对其进行测试时,我意识到在Bytecode中有一些有关泛型类型的信息。 这是我的测试: 我写了2节课: 和 我编译了两个类,并在通用类的某个地方看到了这一行 在非泛型类中: 所以很明显我在字节码中有通用信息,那么这个擦除的东西是什么? 问题答案: 一些通用类型信息存储在属性中。请参阅JLS 4.8 和4.6以及JVM规范4.3.4。

  • 问题内容: 类型擦除应该擦除所有泛型信息…如果是这种情况,那么像GSON这样的库如何使用泛型来确定反序列化为哪种类型? 例如 这将反序列 化为 将反序列化为 因此以某种方式在运行时使用通用信息。 问题答案: 类型擦除不会擦除所有类型信息。它不会从类,字段,返回类型和参数定义中将其删除。保留以下示例中的类型信息: 这是可以通过反射实现的。您可以检查给定的是否是该类,将其强制转换为该类并获取类型信息。

  • 问题内容: 有没有一种方法可以避免类型擦除并获得对类型参数的访问? 我需要了解并使用它来做事。是否可以,如果可以,如何在 不 将类传入构造函数或参数之外的任何地方的 情况下 完成操作? 编辑: 这个问题的主要目的是找出是否有 任何实用的方法 来消除类型擦除。 问题答案: 实际上, 没有 类型擦除的实用方法,因为您不能要求运行时无法访问的内容。当然,假设您同意为实现接口的每个枚举子类化通用类是一个实

  • 问题内容: 我是从Joshua Bloch的google I / O困惑者演讲中得到的。这是代码 这个main方法会引发异常,因为它是原始类型,因此in中的所有泛型都将被删除,因此最终调用而不是。 我的问题是,即使我打电话是不是应该把它调用的方法,因为由于类型擦除,这种方法是有效的并且是类型的不是? 问题答案: 被调用的方法是在编译时定义的,而不是在运行时定义的。 如果在构造函数调用中添加参数,则

  • 我知道在Java泛型中,当使用具有多个边界的类型参数时,编译器会将类型信息擦除到“最左边的边界”(即列表中的第一个类/枚举或接口)。那么为什么以下代码编译没有问题呢? 类型参数不应该被视为对象吗??(因此不允许我调用close()或append())??

  • 我有一个这样定义的方法: 我的单元测试我错误地这样测试它: 这应该会产生编译时错误(当我尝试使用javac编译它时,它会产生编译时错误),但eclipse允许它编译。 我真的不明白为什么eclipse允许这段代码编译,有人能提供一些信息吗,为什么这会在eclipse中编译? eclipse版本是:面向Web开发人员的eclipse Java EE IDE。版本:Luna Service Relea