java的泛型
泛型:
表示数据类型(这种数据类型是引用类型)的一种类型。如int a = 1;变量a为1。类比得 E = String,E表示泛型,他可以表示所有的数据类型,这里这个泛型表示String类型
1. 泛型又称参数化类型,解决数据类型的安全性问题
2. 在类声明或实例化时指定好需要的类型即可(即传入实参)
3. 泛型的作用:可以在类声明时通过一个标识表示类中的某个属性类型,或某个方法的返回值类型,或参数类型
public class Generic{ public static void main(String[] args){ //注意:E的具体类型是在编译期间确定的,这里泛型E的类型表示Srting类型 Person<String> person = new Person<String>("zhangsan"); } } class Person<E>{ E s; //某个属性类型 public Person(E s){//参数类型 this.s = s; } public E f(){//某个方法的返回值类型 return s; } void show(){ System.out.println(s.getclass());//这个看E的实际类型(运行类型) } }
泛型的声明:
class 类名<E,K,M>{}和interface 接口名<T,V>{}
E,K,M,T,V表示泛型,只能表示引用类型,任意字母都行。一般在一个对象实例化就能指定泛型表示的具体类型了
在指定泛型的具体类型后,可以传入该类型或该类型的子类型
泛型的使用形式:
Person<String> person = new Person<String>("zhangsan");
也可以为:Person<String> person = new Person<>("zhangsan");后面的<>中的类型会自动推导,推荐使用第二种
自定义泛型类:
class 类名<E,K,M>{}
1. 普通成员(属性、方法)可以用泛型修饰
2. 使用泛型的数组不能初始化。因为数组在new时,不能确定T的类型,就无法确定要分配多大的空间
3. 静态方法中不能使用泛型。因为静态方法和类相关,在类加载时,对象还没有创建,所以如果静态方法或静态属性使用了泛型,JVM就无法完成初始化。
4. 泛型类的类型是在创建对象时确定的。因为创建对象时,需要指定确定类型
5. 如果在创建对象时,没有指定类型,默认是Object
public class Customgeneric{//其他外部类 public static void main(String[] args){ //注意:E的具体类型是在编译期间确定的,这里泛型E的类型表示Srting类型 Person<String> person = new Person<String>("zhangsan"); Person person = new Person("zhangsan"); //相当于Person<Object> person = new Person<>("zhangsan"); } } class Person<E>{ E s; //某个属性类型 E[] arr;//E[] arr = new E[]; 使用泛型的数组不能初始化 //static E a; //public static E m(E str){} 静态方法中不能使用泛型 public Person(E s){//参数类型 this.s = s; } public E f(){//某个方法的返回值类型 return s; } void show(){ System.out.println(s.getclass());//这个看E的实际类型(运行类型) } }
自定义泛型接口:
interface 接口名<T,V>{}
1. 静态成员也不能使用泛型(接口中的属性默认有public static final)
2. 泛型接口的类型,在继承接口(即在extend后面要指定确定的类型)或实现接口(在implement后面指定具体的类型)时确定
3. 没有指定类型,默认是Object
泛型方法:
访问修饰符 <T,R> 返回值 方法名(参数列表){
}
1. 泛型方法可以定义在普通类中,也可以定义在泛型类中
2. 当调用泛型方法时,就要确定泛型的类型
3. 如public void eat(E e){}这种,访问修饰符后没有<T,R>,那么eat就不是个泛型方法,只是使用了泛型
public class CustomMethodgeneric{ public static void main(String[] args){ Car car = new Car(); car.fly("保时捷",100);//当调用方法时,传入参数,编译器会确定具体的类型 } } class car{//普通类 public void run(){//普通方法 } //<T,R>是泛型,是提供给fly方法使用的 public <T,R> void fly(T t,R r){//泛型方法在普通类中 } } class fish<T,R>{//泛型类 public void run(){ } public<U, M> void eat(U u,M m){//泛型方法在定义在泛型类中 } } class Fish<T,R>{ public void run(){ }public<U,M> void eat(U u,M m){//泛型方法 } //hi不是泛型方法,hi使用了类声明的泛型 public void hi(T t){ } //泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型 public<K> void hello(R r, K k){ } }
泛型和通配符:
约束泛型的范围
1. 通配符 <?> :表示支持任意的泛型类型
2. 通配符 <? extends A>:表示支持A类以及A类的子类,限制泛型的范围在A以下
3. 通配符 <?super A>:表示支持A类以及A类的父类(不限于直接父类),限制泛型的范围在A以上