Java 泛型:是与对象的关系
Java generics: is-A relation to Object
我正在尝试了解 泛型 class 及其具体实例的特征,以及 泛型集合的特征 .
假设我定义了一个泛型 class:Stack<T>
现在我正尝试以这种方式使用它:
Stack<String> ts = new Stack<>(5);
Stack<Object> to = new Stack<>(5);
to = ts // compilation error!
很明显 Stack<String>
不是 Stack<Object>
。
定义通用集合时我感到困惑:
Set<E> elemnts = new Hashset<>();
并注意到我可以使用 elements.toString()
!这意味着 Set<E> elemnts
扩展了 Object
!
那么这里到底发生了什么?
编译错误并不意味着 String
不是 Object
,这是不正确的。例如,下面的代码工作得很好:
String s = "I am String!";
Object o = s;
错误的意思是 Stack<String>
不是 Stack<Object>
。例如,您可以在 Stack<Object>
上调用 push(new Object())
,但显然不能在 Stack<String>
.
上调用
对于以下内容:
Stack<String> ts = new Stack<>(5);
Stack<Object> to = new Stack<>(5);
to = ts // compilation error!
是的,这个编译失败了,因为泛型本质上是编译器强制类型安全的一个特性。就虚拟机而言,他们实际上只有一个Stackclass。
这条语句:
Set<E> elemnts = new Hashset<>();
相当于:
Set<E> elemnts = new Hashset<E>();
该表示法是在 Java 7 中引入的,有时由于 <>
而被称为 'diamond operator'。只是为了去除冗余。
它是扩展对象的集合 class,就像 Java 扩展对象中的所有 classes 一样。
以下内容适用于代码中的 Class 对象:
boolean b = ts.getClass() == to.getClass(); // b is true
字符串 class 是对象的隐式子class。由于对象 class 是 java 中所有 class 的超级 class。因此下面的陈述是有效的
String x="hello";
Object o= x;
但是 Stack<String>
不是 Stack<Object>
的子 class。因此代码给出编译时错误。
Stack<String> ts = new Stack<>(5);
Stack<Object> to = new Stack<>(5);
to = ts // compilation error!
那么 Java 中的泛型到底是什么? 如 , the generic types are compiler enforcements. To be exact, at runtime, the generic types do not exist anymore. They are replaced by Object
or the upper bound of a generic type. This process is called Type Erasure 所述。因此,泛型类型仅在编译时存在。
那为什么我们不能把一个ArrayList<String>
转换成一个ArrayList<Object>
呢?即使类型参数处于一个关系中(String
是 Object
),通用的 类 没有。让我举一个简单的例子。如果
ArrayList<String> strings = new ArrayList<String>();
ArrayList<Object> objects = strings;
有可能,如果有人打电话
objects.add(new Object());
会发生什么?因为 strings
只能容纳 String
s,所以 Java 不能 "put" 一个 Object
进入这个列表。但另一方面,如果您查看 objects
的声明,没有任何暗示,这不应该起作用。因此,Java 不允许在泛型 类 之间进行转换,即使泛型类型处于关系中。
但是泛型类型在运行时不存在。那么什么是喧嚣? ArrayList<String>
在运行时真的不应该是 ArrayList<Object>
吗?因此,所有这些都不重要吗? 嗯,不。由于您在编译时知道类型,因此可以使用某些契约。例如,当从 ArrayList<String>
中检索一个元素时,可以确定此检索到的对象具有 public char charAt(int)
方法(因为 String
具有此方法)。如果出于某种原因,此 ArrayList<String>
会 return 一个 Object
而不是 String
,则无法调用 charAt(int)
方法。
我正在尝试了解 泛型 class 及其具体实例的特征,以及 泛型集合的特征 .
假设我定义了一个泛型 class:Stack<T>
现在我正尝试以这种方式使用它:
Stack<String> ts = new Stack<>(5);
Stack<Object> to = new Stack<>(5);
to = ts // compilation error!
很明显 Stack<String>
不是 Stack<Object>
。
定义通用集合时我感到困惑:
Set<E> elemnts = new Hashset<>();
并注意到我可以使用 elements.toString()
!这意味着 Set<E> elemnts
扩展了 Object
!
那么这里到底发生了什么?
编译错误并不意味着 String
不是 Object
,这是不正确的。例如,下面的代码工作得很好:
String s = "I am String!";
Object o = s;
错误的意思是 Stack<String>
不是 Stack<Object>
。例如,您可以在 Stack<Object>
上调用 push(new Object())
,但显然不能在 Stack<String>
.
对于以下内容:
Stack<String> ts = new Stack<>(5);
Stack<Object> to = new Stack<>(5);
to = ts // compilation error!
是的,这个编译失败了,因为泛型本质上是编译器强制类型安全的一个特性。就虚拟机而言,他们实际上只有一个Stackclass。
这条语句:
Set<E> elemnts = new Hashset<>();
相当于:
Set<E> elemnts = new Hashset<E>();
该表示法是在 Java 7 中引入的,有时由于 <>
而被称为 'diamond operator'。只是为了去除冗余。
它是扩展对象的集合 class,就像 Java 扩展对象中的所有 classes 一样。
以下内容适用于代码中的 Class 对象:
boolean b = ts.getClass() == to.getClass(); // b is true
字符串 class 是对象的隐式子class。由于对象 class 是 java 中所有 class 的超级 class。因此下面的陈述是有效的
String x="hello";
Object o= x;
但是 Stack<String>
不是 Stack<Object>
的子 class。因此代码给出编译时错误。
Stack<String> ts = new Stack<>(5);
Stack<Object> to = new Stack<>(5);
to = ts // compilation error!
那么 Java 中的泛型到底是什么? 如 Object
or the upper bound of a generic type. This process is called Type Erasure 所述。因此,泛型类型仅在编译时存在。
那为什么我们不能把一个ArrayList<String>
转换成一个ArrayList<Object>
呢?即使类型参数处于一个关系中(String
是 Object
),通用的 类 没有。让我举一个简单的例子。如果
ArrayList<String> strings = new ArrayList<String>();
ArrayList<Object> objects = strings;
有可能,如果有人打电话
objects.add(new Object());
会发生什么?因为 strings
只能容纳 String
s,所以 Java 不能 "put" 一个 Object
进入这个列表。但另一方面,如果您查看 objects
的声明,没有任何暗示,这不应该起作用。因此,Java 不允许在泛型 类 之间进行转换,即使泛型类型处于关系中。
但是泛型类型在运行时不存在。那么什么是喧嚣? ArrayList<String>
在运行时真的不应该是 ArrayList<Object>
吗?因此,所有这些都不重要吗? 嗯,不。由于您在编译时知道类型,因此可以使用某些契约。例如,当从 ArrayList<String>
中检索一个元素时,可以确定此检索到的对象具有 public char charAt(int)
方法(因为 String
具有此方法)。如果出于某种原因,此 ArrayList<String>
会 return 一个 Object
而不是 String
,则无法调用 charAt(int)
方法。