一、什么是泛型

泛型,即“参数化类型”。

提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。

那么参数化类型怎么理解呢?就是将类型由原来的具体的类型参数化,此时类型也定义为参数形式(可称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。

二、看看系统怎么用泛型的
public interface List<E> extends Collection<E> {
    E get(int index);
    ……
}

List<String> list = ArrayList<String>();

List接口中的E是类型形参,且get()方法的返回结果也直接是此形参类型(即对应的传入的类型实参)。

三、自定义泛型接口、泛型类和泛型方法

举例:

{
<span >		</span>Test<String> test = new Test<String>("aaa");
		System.out.println(test.getData());
		
		Test<String> t1 = new Test<>("abc");
		Test<Integer> t2 = new Test<>(123);
		System.out.println(t2.getClass().toString()+"000"+t1.getClass());      //同一类型
	}
	
	class Test<T>{
		private T data;
		
		public Test(){};
		
		public Test(T data){
			this.data = data;
		}
		
		public T getData(){
			return data;
		}
	}

1)在泛型接口、泛型类、泛型方法的定义过程中,我们常见的如T、E、K、V等形式的参数常用于表示泛型形参,由于接受来自外部使用时候传入的类型实参。那么对于不同传入的类型实参,生成的相应对象实例的类型是不是一样的呢?

2)使用泛型类时,虽然传入了不同的泛型实参,但并没有真正意义上生成不同的类型,传入不同泛型实参的泛型类在内存上只有一个,即还是原来的最基本的类型(本例中为Test),当然,在逻辑上可理解成多个不同的泛型类型。

究其原因,Java中泛型这一概念提出的目的,导致其只是作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦除,即成功编译后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。

对此总结成一句话:泛型类型在逻辑上可看成是多个不同类型,实际上都是相同的类型。

四、类型通配符

再看一个例子:

{
		Test<String> t1 = new Test<>("abc");
		Test<Integer> t2 = new Test<>(123);
		System.out.println(t2.getClass().toString()+"000"+t1.getClass());
		
		getData(t1);
		getData(t2);
	}
	
	private void getData(Test<Integer> test){
		System.out.println(test.getData());
	}

getData(t2);这句话编译时就报错:The method getData(Test<String>) in the t ype GenericTest is not applicable for the arguments (Test<String>)


要解决上述问题,我们需要一个在逻辑上可用来表示同时是Test<Integer>和Test<String>的父类的一个引用类型,由此,通配符诞生了。

类型通配符一般是使用?代替具体的类型实参。注意,此处是类型实参,不是类型形参。且Test<?>在逻辑上是Test<Integer>、Test<Number>、Test<String>等所有Test<具体实参类型>的父类。由此,我们可定义泛型方法,来完成此类需求:

private void getData(Test<?> test){
		System.out.println(test.getData());
}
类型通配符上限和下限

上例中,如果需要定义一个功能类似于getData(),但对类型实参又有进一步的限制:只能是Number类及其子类。此时需要用到类型通配符上限:

private void getDataUpper(Test<? extends Number> test){
		System.out.println(test.getData());
}

类型通配符上限通过Test<? extends Number>形式定义;相对应的,类型通配符下限为Test<? super Number>形式,其含义与类型通配符下限正好相反。


Java中没有所谓的泛型数组一说。