今天记录一下Java中的泛型,毕竟大家在项目中经常用到或者者看到过。
参考:https://www.songma.com/p/95f349258afb
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数,Java语言引入泛型的好处是安全简单
在Java SE 1.5之前,没有泛型的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换而这种转换是要求开发者对实际参数类型预知的情况下进行的。对于强制类型转换错误的情况,编译器在编译期间可能不提醒错误,在运行的时候才出现异常,这是一个安全隐患。泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,可以提高代码的重用率。
拿我们常用的List集合举个例子:
List mList =new LinkedList();mList.add("aaa");int a = (int) mList.get(0);
不用说这样一运行一定会报一个类型不能转换的错误。注意尽管不正确但编译器没有发现,运行时才会报错,那我们试试加泛型的。
泛型有三种分类:泛型类、泛型接口、泛型方法
泛型类的定义方式:
public class generic<泛型通配符>{private 泛型通配符 genericClass; //泛型构造方法形参 parameter的类型也为T,T的类型由外部指定public Generic(T parameter) { this.genericClass = parameter; }}
这个泛型通配符可以随便取值:比方A,B,C,D.(注意得是大写)但我们通常都取?、K、V各自有不同的含义:
- ?:表示不确定的java类型
- T:(type) 表示具体的一个java类型
- K V (key value) 分别代表java键值中的Key Value
- E: (element) 代表Element
我们就以K,V这种的通配符定义一个泛型类,代码如下:
public interface GenericInter<K,V> { public K getKey(); public V getValue();}public class GenericClass<K,V> extends GenericInter{ public K key; public V value; public GenericClass(K key, V value) { this.key = key; this.value = value; } @Override public Object getKey() { return key; } @Override public Object getValue() { return value; }}
调用:
GenericClass genericClass =new GenericClass("0","张三"); GenericClass mGenericClass =new GenericClass(1,111);
假如要定义超过两个,三个或者三个以上的泛型参数可以使用T1, T2, ..., Tn,列如:
public class GenericClass<T1,T2,T3>{ public T1 t1; public T2 t2; public T3 t3; public GenericClass(T1 t1, T2 t2, T3 t3) { this.t1 = t1; this.t2 = t2; this.t3 = t3; } }
我们上面定义泛型类的时候用的就是泛型接口,泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中:
public interface GenericInter<K,V> { public K getKey(); public V getValue();}
先说一下泛型类和泛型方法的区别:泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型 。泛型方法相比照较复杂,我们来看一下:
真正的泛型方法长这样:
class genericClass<T> { public T t; public genericClass(T t) { this.t = t; } public T getT(){ return t; } //正确的泛型方法 public <T> T getGenericClassT(genericClass<T> obj){ return obj.getT(); } }
要点:真正的泛型方法,在public与返回值之间的<T>必不可少,这表明这是一个泛型方法,并且公告了一个泛型T。但T可以出现在这个泛型方法的任意位置, 泛型的数量也可以为任意多个
这个没啥好说的。
关于如何正确创立泛型数组:
//错误创立泛型数组的方式 List<String> [] mList =new ArrayList<String>[10]; //正确创立泛型数组方式一,通过通配符? List<?> [] mListTwo =new ArrayList<?>[10]; //正确创立泛型数组方式二 List<String>[] mListThree = new ArrayList[10];
总结:在java中是不能创立一个确切的泛型类型的数组
ArrayList<T> al=new ArrayList<T>(); 指定集合元素只能是T类型
ArrayList<?> al=new ArrayList<?>(); 集合元素可以是任意类型,没有意义,一般只是为了说明用法.
- Object和T不同点在于,Object是一个实打实的类,并没有泛指谁,而T可以泛指Object,比如public void printList(List<T> list){}方法中可以传入List<Object> list类型参数,也可以传入List<String> list类型参数,但是public void printList(List<Object> list){}就只可以传入List<Object> list类型参数,由于Object类型并没有泛指谁,是一个确定的类型
- ?和T区别是?是一个不确定类,?和T都表示不确定的类型 ,但假如是T的话,函数里面可以对T进行操作,比如 T car = getCar(),而不能用? car = getCar()。
3.假如T是Java类型则直接T.calss
public Class<?> clazz;
public Class<T> clazz;
由于T需要指定类型,所以当不知道定公告什么类型的Class的时候可以定义一个Class<?>,Class<?>可以用于参数类型定义,方法返回值定义等。
以上就是今天的一律内容!