Java泛型
是什么
类型的参数化机制,将类型当成参数通过<>传给对应的类/接口/方法。
先看一个简单的例子
package testSwitch; //<T>就是定义的泛型 class Generics <T>{ T data; public T getData() { return data; } public void setData(T data) { this.data = data; } } public class TestGenerics { public static void main(String[] args) { //初始化时通过<Integer>的指定类型为Integer Generics<Integer> genericsObject = new Generics<Integer>(); genericsObject.setData(10); Integer i = genericsObject.getData(); System.out.println(i); } }
他背后是什么原理呢?
类型擦除:在编译的时候是将所有的泛型类型T看成Object类型,然后根据T进行安全的强制转换。
这一点我们可以通过反编译清楚的看出来
class Generics { Generics() { } //这里把所有的T都看成了Object类型 public Object getData() { return data; } public void setData(Object data) { this.data = data; } Object data; } public class TestGenerics { public TestGenerics() { } public static void main(String args[]) { Generics genericsObject = new Generics(); genericsObject.setData(Integer.valueOf(10)); //这里增加的强制类型转换 Integer i = (Integer)genericsObject.getData(); System.out.println(i); } }
使用泛型有什么好处?
- 一套模板可以复用到很多类型中。
- 强类型检查,保证了在编译器的类型安全。
下面还有几种使用场景的代码
- 泛型方法
//声明 public <T> void showData(T t) { System.out.println(t + " and data " + data);; } //调用,直接赋值就可以了 genericsObject.showData(20)
- 泛型限定为某一类型及其子类: <T extends Number>
- 泛型限定为某一类型及其父类: <T super Number>
class Generics { int data; //限定为Number的子类 public <T extends Number> void showData(T t) { System.out.println(t + " and data " + data);; } } public class TestGenerics { public static void main(String[] args) { Generics genericsObject = new Generics(); genericsObject.showData(12.2); } }
- 原始泛型类没有限定,但是我在使用的时候想加个限定,比如必须是某一类型及其子类:<? extends Number>
package testGenerics; //定义原始无限定泛型 class Generics <T>{ T data; public Generics(T data) { this.data = data; } public void showData() { System.out.println(data); } } class GenericsHelper{ //在其他类中使用的时候限定泛型类型 public static void showNewData(Generics<? extends Number> gen) { gen.showData(); } } public class TestGenerics { public static void main(String[] args) { GenericsHelper.showNewData(new Generics<Integer>(10)); } }
- 还有一种不常用,通配符<?>,一般用于获取类类型中。
Class<?> classType = Class.forName(Java.lang.String);
有什么缺点吗?
- T不能是基本类型(因为Object无法持有基本类型)
- 无法取得泛型的Class,只能获取到Pair
- 无法判断带泛型的Class
- 不能创建具体类型的泛型数组