5.3 KiB
5.3 KiB
11.泛型
11.1 什么是泛型
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
首先来看一个例子
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类型。
泛型使得代码可以被不同类型的对象重用
11.2 泛型类
一个泛型类就是拥有一个或者多个类型变量的类。下面看一个简单例子:
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,是形式类型参数,可以随意指定,当类被使用的时候,就会使用具体的实际类型参数。
需要注意的是,泛型类只能用在成员变量上,并且只能使用引用类型。
11.3 泛型方法
下面是定义泛型方法的规则:
- 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前
- 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
- 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
- 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像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));
}
11.4 泛型接口
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()) ;
}
};
11.5 类型通配符
类型通配符一般是在不确定具体参数时候,使用?代替。?表示未知类型,类型参数赋予不确定值,只能用在声明类型、方法参数上,不能用在定义泛型类上
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>());
}
}