1 泛型类
泛型允许对类型进行抽象,最常见的泛型类是容器类。例如:
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
for(String s: list) {
System.out.println(s);
}
以上例子中,如果试图向list中添加一个Integer对象,那么会导致编译错误。编译器会进行类型检查,这避免了使用非泛型容器类时常见的强制类型转换。泛型类是具有一个或者多个类型变量(type variable)的类。以下是个简单的例子:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Bag<E> {
private List<E> bag = new ArrayList<E>();
public Iterator<E> iterator() {
return this.bag.iterator();
}
public boolean add(E e) {
return this.bag.add(e);
}
public boolean remove(Object o) {
return this.bag.remove(o);
}
public boolean contains(Object e) {
return this.bag.contains(e);
}
public boolean addAll(Bag<? extends E> b) {
return this.bag.addAll(b.bag);
}
public boolean removeAll(Bag<?> b) {
return this.bag.removeAll(b.bag);
}
public boolean containsAll(Bag<?> b) {
return this.bag.containsAll(b.bag);
}
public void clear() {
this.bag.clear();
}
List<E> getBag() {
return this.bag;
}
}
import java.util.Collections;
import java.util.Comparator;
public class Bags {
public static <E> void sort(Bag<E> b, Comparator<? super E> c) {
Collections.sort(b.getBag(), c);
}
public static <T extends Comparable<? super T>> T max(Bag<T> b) {
return Collections.max(b.getBag());
}
public static <E> void copy(Bag<E> dest, Bag<? extends E> src) {
dest.addAll(src);
}
}
需要注意的是,不能抛出或者捕获泛型类的实例,泛型类继承自Throwable也是不合法的。此外也不能声明泛型类实例的数组,例如以下代码会造成编译错误:
Bag<Integer> b3[] = new Bag<Integer>[10]; // Cannot create a generic array of Bag<Integer>
2 泛型方法
泛型方法是指带有类型参数的方法,类型变量的位置是修饰符和返回类型之间。在调用泛型方法的时候,具体类型的位置是方法名前的尖括号中,在绝大多数的情况下,由于编译器可以判断出具体类型,因此也可以省略具体类型。以下是个简单的例子:
public class Base {
public String getName() {
return "Base";
}
public static <T> void print(T t) {
System.out.println(t.toString());
}
public static void main(String args[]) {
Base base = new Base();
Base.<Base>print(base);
Base.print(base);
}
}
以上例子中的print方法内只能调用T从Object类继承的方法。如果希望将T限定为Base及其子类,那么可以使用extends设定上限,或者使用super设定下限(C++中不能限定参数变量的类型),例如:
public static <T extends Base> void print(T t) {
System.out.println(t.getName());
}
类型变量也可以有多个限定,限定类型用&分割。如果限定类型可以包含多个接口,但是至多有一个类(单继承),如果有一个类,那么它必须是第一个限定类型。例如:
T extends Comparable & Serializable
3 擦除
编译器会为每个泛型类型自动提供一个原始类型(raw type)。其类型变量会被擦除(因此Java泛型没有C++模板类的代码膨胀问题),并用其限定类型代替,如果没有限定类型,那么使用Object。不能使用原始数据类型作为类型变量,例如没有Bag<int>,但是可以有Bag<Integer>。 由于类型变量会被擦除,因此不管泛型类的类型变量是什么,它的所有实例的运行时类是相同的,例如以下代码的输出如下:
Bag<Integer> b1 = new Bag<Integer>();
Bag<String> b2 = new Bag<String>();
System.out.println(b1.getClass());
System.out.println(b2.getClass());
System.out.println(b1.getClass() == b2.getClass());
class Bag
class Bag
true
由于类的静态成员变量和成员方法也被类的所有实例共享,因此不能在类的静态成员变量和成员方法中引用类型变量。例如以下的代码会导致编译错误:
public class Bag<E> {
private static E INSTANCE; // Cannot make a static reference to the non-static type E
public static E getInstance() { // Cannot make a static reference to the non-static type E
return INSTANCE;
}
}
不能通过类型变量构造实例,但是可以通过Class.newInstance和Array.newInstance来构造实例。例如以下的代码会造成编译错误:
public Bag() {
E e1 = new E(); // Cannot instantiate the type E
E e2[] = new E[10];
}
在擦除后,也不能引起冲突。考虑如下代码:
public class Bag<E> {
public boolean equals(E e) { // Name clash: The method equals(E) of type Bag<E> has the same erasure as equals(Object) of type Object but does not override it
return true;
}
}
以上的Bag类的类型变量被擦除后的代码如下:
public class Bag<E> {
public boolean equals(Object e) {
return true;
}
}
其equals方法与Object.equals(Object obj)方法冲突。
分享到:
相关推荐
在Java编程语言中,泛型(Generic)是一个强大的特性,它允许我们在编译时检查类型安全,并且可以消除运行时的类型转换。泛型引入的主要目的是提高代码的重用性、安全性和效率,同时减少类型转换的繁琐工作。这篇...
1. **泛型的基本概念**:泛型是Java中的一种模板类或接口,它允许开发者在定义类、接口和方法时使用类型参数,而不是具体的类型。这就像创建了一个可以适用于多种类型的通用容器。 2. **泛型的语法**:在类的声明中...
Java1.5泛型指南中文版(Java1.5 GenericTutorial)
标题中的"Generic_MT4_java_generic_mt4_"暗示了一个与MetaTrader 4 (MT4)交易平台相关的编程项目,可能是一个自定义的智能交易系统(Expert Advisor,EA)或指标,使用了Java语言,并且具有通用性。这个“Generic_...
Generic Variance java 源码
Generic Stack java 源码
### 泛型编程在科学计算中的应用:C++、Java与C#的比较 #### 摘要概览 本文是一篇关于泛型编程在科学计算领域应用的研究论文。研究对比了Java、C#和C++三种语言在实现泛型(参数化类型)方面的表现,并重点介绍了...
在《java-generic.rar》压缩包中包含的《java generic.pdf》文件,很可能是详细阐述了以下几个关于Java泛型的核心知识点: 1. **类型参数化**:泛型的核心在于类型参数化,这使得我们可以在定义类、接口和方法时...
本文将深入探讨Java中的浅复制和深复制,并以Android为背景,结合具体的实例讲解如何实现Java泛型深拷贝。 首先,我们要理解浅复制和深复制的概念。浅复制(Shallow Copy)是指创建一个新的对象,然后将原对象引用...
### Java泛型编程详解 #### 引言 Java 5引入了多项语言级别的扩展功能,其中最为重要的一项就是泛型(Generics)的引入。本文档旨在为读者介绍Java中的泛型概念及其用法。 如果你熟悉其他语言如C++中的模板...
"Generic22BW.zip"是一个压缩包文件,其命名方式暗示它可能是一个通用或标准的软件版本,"BW"可能是“Black and White”或者“Basic Version”的缩写,表明这可能是一个简化版或黑白主题的版本。从标签"Generic22...
11.4java-泛型(Generic)
标签:apache、velocity、tools、generic、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明...
java高手真经 全光盘源代码 打包rar 第1部分(2个程序包) HelloWorld.zip 01.Java入门样例Hello...javageneric.zip 27.Java泛型编程 javaannotation.zip 28.Java注释符编程 javafeature.zip 29.Java5.0语言新特性
1. **泛型数组的创建**:在 Java 中,直接创建泛型数组是不可能的,而应当采用 `Array.newInstance` 或其他替代方案。 2. **类型擦除的影响**:Java 泛型在运行时会被擦除为其原始类型,这限制了泛型数组的使用。 3....
该文件里包含两个.jar包: collections-generic-4.01.jar和looks-2.1.4.jar, 引入collections-generic-4.01.jar: 右击工程--》Build path ——》Add External JAR-->选中collections-generic-4.01.jar --》OK 在源...