泛型的概念及作用
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,即给类型指定一个参数,然后在使用时再指定此参数具体的值,那样这个类型就可以在使用时决定了。这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
List<? extends String> extendsList = new ArrayList<>();
List<? super String> superList = new ArrayList<>();
特性
泛型只在编译阶段有效。
List<String> stringArrayList = new ArrayList<String>();
List<Integer> integerArrayList = new ArrayList<Integer>();
Class classStringArrayList = stringArrayList.getClass();
Class classIntegerArrayList = integerArrayList.getClass();
if(classStringArrayList.equals(classIntegerArrayList)){
System.out.println("类型相同")
}
在编译之后程序会采取去泛型化的措施。也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息输出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。对此总结成一句话:泛型类型在逻辑上可以看成是多个不同的类型,实际上都是相同的基本类型。
该如何使用泛型
泛型类型必须是引用类型(非基本数据类型)
泛型类
public class GenericDemo<T> {
private T value;
public GenericDemo(T value) {
this.value = value;
}
public <T> void f(T x) {
System.out.println(x.getClass().getName());
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
GenericDemo<String> stringGenericDemo = new GenericDemo<>("泛型类");
System.out.println(stringGenericDemo.getValue());//输出"泛型类"
泛型接口
public interface Generator<T> {
void show(T value);
}
public class IntegerGeneratorImpl implements Generator<Integer> {
@Override
public void show(Integer value) {
System.out.println(value);
}
}
public class StringGeneratorImpl implements Generator<String> {
@Override
public void show(String value) {
System.out.println(value);
}
}
Generator<String> generator = new IntegerGeneratorImpl();//编译异常
Generator g1 = new IntegerGeneratorImpl();//正确
Generator g2 = new StringGeneratorImpl();//正确
泛型方法
只有声明了的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
//泛型方法
public <T> void f(T t) {
System.out.println(t);
}
//非泛型方法,如果在非泛型类中使用该方法会编译出错,但是上面这个在非泛型类中可以正常运行
public void f(T t) {
System.out.println(t);
}
举例
public class GenericMethodTest
{
// 泛型方法
public static < E > void printArray( E[] inputArray )
{
// 输出数组元素
for ( E element : inputArray ){
System.out.printf(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( "Array integerArray contains:" );
printArray( intArray ); // 传递一个整型数组
System.out.println( "\nArray doubleArray contains:" );
printArray( doubleArray ); // 传递一个双精度型数组
System.out.println( "\nArray characterArray contains:" );
printArray( charArray ); // 传递一个字符型型数组
}
}
泛型通配符
<?>
表示类型参数可以是任何类型
<T extends A>
使用固定上边界的通配符的泛型, 就能够接受指定类及其子类类型的数据。
List<? extends Animal> animals = null;
animals=new ArrayList<Cat>();
animals=new ArrayList<Dog>();
animals=new ArrayList<String>();//编译不通过
<T supers A>
使用固定下边界的通配符的泛型, 就能够接受指定类及其父类类型的数据。
List<? super Cat> animals = null;
animals=new ArrayList<Cat>();
animals=new ArrayList<Animal>();
animals=new ArrayList<String>();//编译不通过