java的泛型
一、泛型的概念
所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时确定(即传入实际的类型参数,也称为类型实参)。
二、泛型的引入背景
集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,JDK1.5之后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。Collection,List,ArrayList 这个就是类型参数,即泛型。
eg1:
看一下简单的案列
import java.util.ArrayList; import java.util.List; public class test { public static void main(String[] args) { List list = new ArrayList(); list.add("string"); list.add(100); for (int i = 0; i < list.size(); i++) { String name = (String) list.get(i); // 1 System.out.println("name:" + name); } } }
上述代码会出现 Exception in thread “main” java.lang.ClassCastException 错误
ArrayList由String类型和Integer类型,而两者都以String格式使用,所以出现了上述错误。
这个时候就用得上泛型了
import java.util.ArrayList; import java.util.List; public class test { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("string"); list.add(100); for (int i = 0; i < list.size(); i++) { String name = list.get(i); // 2 System.out.println("name:" + name); } } }
上述代码会编译错误,如果使用idea的话,会出现下述错误提示
java: 对于add(int), 找不到合适的方法 方法 java.util.Collection.add(java.lang.String)不适用 (参数不匹配; int无法转换为java.lang.String) 方法 java.util.List.add(java.lang.String)不适用 (参数不匹配; int无法转换为java.lang.String)
这里通过List<String>限定了集合内的元素只能是String类型。
泛型使得代码可以被不同类型的对象重用
泛型总结:
- ① 集合接口或集合类在jdk5.0时都修改为带泛型的结构。
- ② 在实例化集合类时,可以指明具体的泛型类型
- ③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。
- 比如:add(E e) —>实例化以后:add(Integer e)
- ④ 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
- ⑤ 如果实例化时,没指明泛型的类型。默认类型为java.lang.Object类型
三、泛型类
一个泛型类就是拥有一个或者多个类型变量的类。下面看一个简单例子:
public class test { public static class Point<T> { private T var; public void setVar(T x) { this.var = x; } public T getVar() { return this.var; } } public static void main(String[] args){ Point<Float> p = new Point<Float>() ; p.setVar(new Float(100.12f)) ; System.out.println(p.getVar()); } }
括号里面的T,是形式类型参数,可以随意指定,当类被使用的时候,就会使用具体的实际类型参数。
需要注意的是,泛型类只能用在成员变量上,并且只能使用引用类型。
四、泛型方法
下面是定义泛型方法的规则:
- 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前
- 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
- 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
- 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。
public class MethodTest { int var = 100; String varStr = "Hello Datawhale"; public <T> T Method(T a) { return a; } public static void main(String[] args) { MethodTest t=new MethodTest(); System.out.println(t.<Integer>Method(t.var)); System.out.println(t.<String>Method(t.varStr)); }
五、泛型接口
class InfoImpl implements Info<String>{ // 定义泛型接口的子类 private String var ; // 定义属性 public InfoImpl(String var){ // 通过构造方法设置属性内容 this.setVar(var) ; } @Override public void setVar(String var){ this.var = var ; } @Override public String getVar(){ return this.var ; } } public class GenericsDemo24{ public void main(String arsg[]){ InfoImpl i = new InfoImpl("harvic"); System.out.println(i.getVar()) ; } };
六、类型通配符
类型通配符一般是在不确定具体参数时候,使用?代替。?表示未知类型,类型参数赋予不确定值,只能用在声明类型、方法参数上,不能用在定义泛型类上
public class match { public static void test(List<?> list) { List<?> list2; list2 = new ArrayList<String>(); list2 = new ArrayList<Integer>(); list2 = new ArrayList<Object>(); } public static void main(String[] args) { test(new ArrayList<String>()); test(new ArrayList<Integer>()); } }