概念
泛型,即概念参数化类型,将类型由原来的具体的类型参数化,类似方法中的变量参数,此时类型也定义成参数形式(可以称为类型形参),然后再使用调用时传入具体的类型。
##实例##
先来看看Java自带的例子 List
public class Fxing {
public static void main(String args[]){
List<String> list = new ArrayList<String>();
list.add("qqyumidi");
list.add("corn");
for (int i = 0; i < list.size(); i++) {
String name = list.get(i); // 2
show("name:" + name);
}
}
private static void show(Object object){
System.out.println(object);
}
}
上述列子中将lIst的泛型定义为String类型参数,也就是说,相应的List接口中肯定含有类型形参,且get()方法的返回结果也直接是此形参类型。具体看一下list源码
public interface List<E> extends Collection<E> {
int size();
.......
E get(int index);
/**
* Replaces the element at the specified position in this list with the
* specified element (optional operation).
*/
E set(int index, E element);
/**
* Inserts the specified element at the specified position in this list
* (optional operation). Shifts the element currently at that position
* (if any) and any subsequent elements to the right (adds one to their
* indices).
*/
void add(int index, E element);
/**
* Removes the element at the specified position in this list (optional
* operation). Shifts any subsequent elements to the left (subtracts one
* from their indices). Returns the element that was removed from the
* list.
*/
E remove(int index);
.....
}
我们可以看到,在List接口中采用泛型化定义之后,中的E表示类型形参,可以接收具体的类型实参,并且此接口定义中,凡是出现E的地方均表示相同的接受自外部的类型实参。
我又写了一个例子
public class Fxing {
public static void main(String args[]){
List list = new ArrayList();
list.add("qqyumidi");
list.add("corn");
list.add(100);
for (int i = 0; i < list.size(); i++) {
String name = "123";
if(list.get(i) instanceof String){
name = (String) list.get(i); // 2
}else if(list.get(i) instanceof Integer){
name = (list.get(i)).toString(); // 2
}
show("name:" + name);
}
}
private static void show(Object object){
System.out.println(object);
}
}
从代码中,可以看出,如果没有定义类型参数,也可以传其他参数,但是在输出的时候就要判断是什么类型,这样就比较麻烦了。
写了一个泛型类
package com.yangyi.javaplan.fxing;
/**
* Created by GYH on 2017/3/6.
*/
public class Box<T> {
private T data;
public Box(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
调用
import java.util.ArrayList;
import java.util.List;
/**
* Created by GYH on 2017/3/6.
*/
public class Fxing {
public static void main(String args[]){
Box<String> stringBox = new Box<String>("guoyuehua");
show(stringBox.getClass());
Box<Integer> integerBox = new Box<Integer>(12);
show(integerBox.getClass());
}
private static void show(Object object){
System.out.println(object);
}
}
运行结果
class com.yangyi.javaplan.fxing.Box
class com.yangyi.javaplan.fxing.Box
true
从运行结果可以看出,虽然传入了不同的泛型实参类型,但是并没有真正意义上生成不同的类型,传入不同的类型实参,在内存上只有一个,即还是原来的最基本的类型,当然,逻辑上不同的泛型类型。
原因:在Java中的泛型这一概念提出作用于代码编译阶段,在编译过程中,对于正确检验泛型结果后,会将泛型的相关信息擦出,也就是说,成功编译过后的class文件是不包含任何泛型信息的,泛型信息不会进入到运行时阶段。
那么泛型中父子关系的类型吗
栗子
public class Fxing {
public static void main(String args[]){
Box<Number> numberBox = new Box<Number>(99);
Box<Integer> integerBox = new Box<Integer>(12);
showData(numberBox);
showData(integerBox);
}
private static void showData(Box<Number> box){
show("name: "+ box.getData());
}
private static void show(Object object){
System.out.println(object);
}
}
栗子中Number 和 Integer是父子关系,但是编译时报错,…cannot be applied to …,错误,显然在逻辑上Box不能作为Box 的父类,如果非要用,是不是还要判断类型或者强制转换,这就和泛型提出的理论矛盾了,这个时候类型通配符就来了,类型通配符的使用:代替具体的类型实参(是实参、实参、实参 重要的事情说三遍)
栗子
public class Fxing {
public static void main(String args[]){
Box<Number> numberBox = new Box<Number>(99);
Box<Integer> integerBox = new Box<Integer>(12);
showData(numberBox);
showData(integerBox);
}
private static void showData(Box<?> box){
show("name: "+ box.getData());
}
private static void show(Object object){
System.out.println(object);
}
}
还有在使用的时候还要遇到,限制通配符的上限和下限,比如我要限制传的参数必须是Number的子类等等,那么就需要加上限制。
public class Fxing {
public static void main(String args[]){
Box<Number> numberBox = new Box<Number>(99);
Box<Integer> integerBox = new Box<Integer>(12);
showData(numberBox);
showData(integerBox);
}
private static void showData(Box<? extends Number> box){
show("name: "+ box.getData());
}
private static void show(Object object){
System.out.println(object);
}
}
上面定义的是上限,那么下限定义是:Box<? super Number>
形式
注意:并且还要注意的一点是,Java中没有所谓的泛型数组一说。