原始类型和类型参数

时间:2013-09-30 07:39:36

标签: java generics raw-types

考虑一下官方帮助中的例子:

public class Node<T>{
    private T data;
    public Node(T data){ this.data=data; }
    public void setData(T data){
        System.out.println("Node.setData");
        this.data=data;
    }
}
public class MyNode extends Node<Integer>{
    public MyNode (Integer data){ super(data); }
    public void setData (Integer data){
        System.out.println("MyNode.setData");
        this.data=data;
    }
}
public class MyClass{
    public static void main(String[] args){
        Node n = new MyNode(5);
        n.setData(new Object());//ok
    }
}
  1. 什么意思是Node n= new MyNode(5);Node n是对原始类型的引用,但我将Node<T>描述为泛型类。原始类型Node是否为所有Node<T>的泛型类型T的超类型?是否真的如果我们定义对原始类型Node n的引用,其中Node<T>是泛型类型编译器没有键入选中,但是在Node<T>中启动了类型擦除?编译器默认情况下将TObject匹配的声明是错误的,因为Node<Object>不是Node<Integer>的超类型。

  2. 编译器T中的类型参数Node<T>是什么?编译器考虑T作为参考类型是否属实,但他不知道T的描述?

1 个答案:

答案 0 :(得分:2)

1)

Node n= new MyNode(5);

您有一个指向MyNode对象(Node<Integer>的子类)的原始(未指定类型)节点引用。

  

原始类型Node是否为所有T的泛型类型节点的超类型?

Node不是Node<T>

的超类(超类型)
  

如果我们定义对原始类型Node n的引用是真的,其中Node<T>是泛型类型编译器没有键入选中,但是在Node<T>中启动了类型擦除?

编译器仅检查引用,如果引用是raw,则可以添加所需的任何类型。泛型被引入到Java语言中,以便在编译时提供更严格的类型检查并支持泛型编程。泛型是一个仅编译器的问题,在编译类型被擦除(擦除)和泛型不会产生运行时开销

  

默认情况下,编译器将T与Object匹配的语句是错误的,因为Node<Object>不是Node<Integer>的超类型。

您尚未为通用类Node指定类型,这相当于Node<Object>Node<Object>不是Node<Integer>的超类,也不是Node<A>Node<B> 的任意组合。它们在运行时都是同一个类!

2) 类型T是您在使用时指定的内容。在Node类定义中,T只是一个占位符,因此您可以在下一行中使用相同的类型来指定数据类型。可以将Node<T>中的T视为一个参数,而不是在类中的其他地方使用。 (您可以将T替换为您想要的任何变量,但是除非它是我们使用E的集合,否则使用T是惯例。

考虑以下内容......

public class MyClass extends ArrayList<Integer> {
    public static void main(String[] args) {
        ArrayList<Integer> a = new MyClass();
        a.add(new Integer(5));
        ArrayList b = a;
        b.add(new String("abc"));

        for (Integer i : a) {
            //System.out.print(i);
        }
    }
}

这将编译得很好,因为a是一个ArrayList。

请记住,泛型仅适用于编译器,因此一旦编译它们就不再影响代码了。我们可以使用原始类型的引用b为同一个对象设置别名,从而允许我们将其他对象添加到列表中(例如字符串)。

现在当我们尝试循环遍历整数的ArrayList时,我们惊讶于运行时发现它包含一个String,完全允许添加(因为所有ArrayLists在运行时都是ArrayList<Object>)但是不允许被强制转换为整数。

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at MyClass.main(MyClass.java:11)