泛型
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
泛型的分类:
- 泛型类
- 泛型方法
基本数据类型对应的包装类:
int---->Integer
char—>Character
long—>Long
byte—>Byte
short—>Short
float—>Float
double—>Double
boolean—>Boolean
泛型类
Java可以定义一个基于泛型类型的类。即可以定义一个类,定义时先不指定它要存储、操作的对象类型,而在实例化时才能确定对象类型。泛型有时也称为参数化类型。
泛型类的定义:
基本语法:
class 泛型类名称<类型形参列表> {
// 这里可以使用类型参数
}
泛型类可以一次有多个类型变量,用逗号隔开
class ClassName<T1, T2, ..., Tn> {
}
与类的使用方法相同,也可以继承其他类或实现接口:
class 泛型类名称<类型形参列表> extends 继承类/* 这里可以使用类型参数 */ { // 这里可以使用类型参数
}
class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {
// 可以只使用部分类型参数
}
类型形参一般使用一个大写字母表示,常用的名称有:
- E:表示Element
- K:表示Key
- V:表示Value
- N:表示Number
- T:表示Type
简单示例:
// 1. 尖括号 <> 是泛型的标志
// 2. E 是类型变量(Type Variable),变量名一般要大写
// 3. E 在定义时是形参,代表的意思是 MyArrayList 最终传入的类型,但现在还不知道
public class MyArrayList<E> {
private E[] array;
private int size;
……
加入继承或实现的示例:
public interface MyList<E> {
// 尾插
void add(E e);
// 尾删
E remove();
}
public class MyArrayList<E> implements MyList<E> {
// TODO: 未完成
}
泛型类的使用
语法:
泛型类<类型实参> 变量名; // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参); // 实例化一个泛型类对象
泛型类是作用在编译期间的一种机制
对于泛型在运行期间编译器有一个类型擦除的操作。类型擦除是依据其类型边界而定的。
class MyArrayList<E> {
// E 会被擦除为 Object
}
class MyArrayList<E extends Comparable<E>> {
// E 被擦除为 Comprable
}
编译器在类型擦除阶段的具体操作:
- 将类型变量用擦除后的类型替换,即Object或者Comparable。
- 加入必要的类型转换语句
- 加入必要的bridge method 保证多态的正确性
泛型方法
对于泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当的处理每一个方法调用。
定义泛型方法的规则:
- 所用的泛型方法都有一个类型参数声明部分(由尖括号分隔<>),该类型参数声明部分在方法返回类型之前
- 每一个类型参数声明部分都包含一个或多个类型参数,参数之间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
- 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
- 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int、double、char等)。
简单示例:
public class GenericMethodTest
{
// 泛型方法 printArray
public static < E > void printArray( E[] inputArray )
{
// 输出数组元素
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
public static void main( String args[] )
{
// 创建不同类型数组: Integer, Double 和 Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println( "整型数组元素为:" );
printArray( intArray ); // 传递一个整型数组
System.out.println( "\n双精度型数组元素为:" );
printArray( doubleArray ); // 传递一个双精度型数组
System.out.println( "\n字符型数组元素为:" );
printArray( charArray ); // 传递一个字符型数组
}
}
打印结果:
整型数组元素为:
1 2 3 4 5
双精度型数组元素为:
1.1 2.2 3.3 4.4
字符型数组元素为:
H E L L O