泛型的本质就是参数化类型 ,泛型只在编译阶段有效.
参数化类型
所操作的数据类型被指定为一个参数,这种参数可以用在类.接口和方法的创建中,分为泛型类.泛型接口.泛型方法
泛型好处
- 可以对类型进行自动检查
- 自动对类型进行类型替换
1.泛型类
ublic class test <T>{
private T number ;
//static T num;
public test(T number){
this.number = number;
}
public T getNum(){
return this.number;
}
public void showType(){
System.out.println(number.getClass().getName());
}
public static void main(String[] args) {
test t = new test("sdfsdfsdf");
t.showType();
}
}
- 首先在static方法中,是不能用泛型类型参数的.因为static方法是不依赖对象存在的,因而无法推知static对象的大小
- 不能直接new泛型数组.因为不知到其确切对象,不知道开辟空间的大小
- 不能定义泛型对象的数组.原因同上
- 不能产生泛型类型对象.原因同上
- 泛型类型不能是基本数据类型只能使用引用数据类型.因为泛型对象只能是对象类型
定义的泛型类一定要传入实参吗?
在使用泛型的时候如果传入实参,则会根据传入的泛型实参进行相应的限制,此时泛型才会起到相应的限制作用.如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以是任何的类型.
2.泛型接口
通常把泛型要共同实现的方法的签名封装成泛型接口
与一般接口的声明一致,但需要在声明的泛型接口名称的后面加"<>"执行一个或多个类型参数
public interface myInterface<E >{
void add(E e);
}
在实现泛型接口的类,未传入实参时:
/**
*未传入实参时与泛型类的定义相同,在声明类的时*候,需要将泛型的声明也一起加入到类中
**/
public class test <T>implements Comparable<T>{
@Override
public int compareTo(T o) {
return 0;
}
}
在实现泛型接口的类,传入实参时
/** 直接将实参传给接口
**/
public class test implements Comparable<String>{ @Override
public int compareTo(String o) {
return 0;
}
}
3.泛型方法
首先无论这个类是不是泛型类,都可以包含泛型方法
泛型方法的参数化类型列表放在方法类符后面,返回值之前.
泛型类中使用了泛型的成员方法并不是泛型类,只用声明了< T >才是泛型方法
- < T > 可以理解为声明此方法是泛型方法.
- < T >表名该方法将使用泛型类型T,此时才可一在方法中使用泛型类型T
泛型交换函数:
public <T> void swap(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
3.1 泛型参数的约束
默认情况下 ,没有约束条件的泛型类型参数 < T > 称为为未绑定类型参数.
未绑定类型参数可以接受任意的参数类型.
想要参数支持特定类型时,可以使用extend 或者super进行约束
public static <T extends Comparable<T>> void swap(T[] array, int i, int j) {
if (array[i].compareTo(array[j]) > 0) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
3.2 extends 主要限定泛型参数的上界
< T extends 基类 > : T只能是基类或者基类的派生类
< T extends 基接口> : T只能是实现基接口的派生类
3.3 通配符的约束
<? extends 基类 > : 其中说明?未知类型限定未指定类或者指定类的派生类,指定上界.(**extens 是继承了这个基类,原本所有类继承的都是Object 类,这个将定义了未知类型的上界为这个基类或者派生类**)<? super 派生类 > : 其中? 未知类型限定未指定类的或者指定类的基类,指定下界 (**在我看来,super指定了其父类,因而未知泛型参数最少是这个基类,或者是它的派生类**)