一、泛型介绍
泛型实际就是 一个<>引起来的 参数类型。
当完成一个功能的时候,不确定的数据,会定义为参数。
完成功能,定义类,类型不确定的时候, 我们可以将类型作为参数,或者说将类型泛化。
二、泛型类
自定义泛型类
class Person<T, E, K>{ //泛型类可以定义多个参数类型
T pet;
E food;
public Person() {}
public void test01(K t){
// K[] arr = new K[10]; //使用泛型的数组不能初始化
}
}
注:
1.普通成员变量可以使用泛型(属性、方法)。
2.使用泛型的数组,不能初始化。
3.静态方法中不能使用类的泛型(类中的泛型在创建实例对象的时候才指定,但是静态方法在类加载的时候就有了)。
4.泛型类的类型是在创建对象时确定的(因为创建对象是需要指定确定类型)。
5.创建对象时没有指定泛型类型,则默认Object。
继承情况
//1.父类指定泛型
class SubGenericTest extends GenericTest<Integer>{
//指定父类泛型,那么子类就不需要再指定泛型了,可以直接使用
}
//2.父类不指定泛型
class SubGenericTest2<E> extends GenericTest<E>{
//如果父类不指定泛型,那么子类也会变成一个泛型类;那么E可以在创建子类对象的时候确定
}
三、泛型接口
接口中,静态成员也不能使用泛型。
泛型接口的类型,在继承接口或者实现接口时确定。
没有指定类型,默认Object。
interface Intface<T>{
public static final int a=1;
// T b= new T(); 报错 //1.接口属性默认static 2.属性final必须指定值,但不知道类型无法给值 ->不能使用泛型
}
class IntClass<T> implements Intface<T>{ //这里的T由实现类或者子类给它
}
interface InterFace1<T> extends Intface<T>{ //由子接口给T
}
四、泛型方法
什么是泛型方法:
不是带泛型的方法就是泛型方法。泛型方法有要求:这个方法的泛型的参数类型要和当前的类的泛型无关。换个角度:泛型方法对应的那个泛型参数类型和当前所在的这个类是否是泛型类,泛型是啥无关。
泛型方法定义时,前面要加<T>
原因:如果不加的话,会把T当做一种数据类型,然而代码中没有T类型那么就会报错。
T的类型是在调用方法的时候确定的(传值时确定)
泛型方法可否是静态方法?可以是静态方法
class TestGeneric<E> {
//不是泛型方法 (不能是静态方法)
/*public static void a(E e){ //报错
}*/
//是泛型方法
public static <T> void b(T t){
}
public void c(E e){ //使用类的泛型
}
}
注意:
静态方法中不能使用类的泛型(类中的泛型在创建实例对象的时候才指定,但是静态方法在类加载的时候就有了)。
泛型方法可以是静态的。
五、注意事项:
定义的时候,指定属性类型、参数类型、返回值类型。
使用泛型时,泛型类型必须为引用数据类型,不能为基本数据类型。java的普通方法、构造方法都可以使用泛型,方法使用泛型前必须先对泛型进行声明,可以使用任意字母,一般要大写。
不可以用泛型构造对象,即first = new T(); 是错误的。
使用泛型的方法不能是静态的。在static方法中不可以使用泛型,泛型变量也不可以用static关键字来修饰。
泛型方法可以是静态的。如果一个静态方法需要使用泛型的话,该方法需要定义成泛型方法。
六、泛型通配符<?>和上下边界
当我们定义一个方法的时候,方法本身没有泛型;但是使用的内容带有泛型,此刻又确定不了到底使用哪一种类型。
任意类型都可以即<?>,指支持任意泛型类型。
<? extends A>:支持A以及A的子类,规定了泛型的上限。
<? super A>:支持A以及A的父类,规定了泛型的下限。