含义:
含义:参数化类型。
注意:泛型只在源代码中存在,在编译之后的字节码文件中,泛型又会被转回原始类型。
为什么使用泛型?
- 规定操作的数据类型,避免运行时报错
- 避免强转
案例
下面是没有加泛型的
List arrayList = new ArrayList();
arrayList.add("aaaa");
arrayList.add(100);
假如我们输出arrayList中的值程序就会报错,为什么呢?因为我们往集合中加入了两种不同类型的数据。那么有没有一种办法能让我们在创建对象的时候就规定好对象可以操作的类型呢?泛型就可以
加了泛型之后,如果我们往里面加入int类型的数据,程序已经开始报错了。
List<String> arrayList = new ArrayList<String>();
arrayList.add(100); 报错
在类中使用
先来看语法
class 类名 <泛型名>{
private 泛型名 泛型变量名;
....
}
单单看语法可能回有点晕,实际上就是泛型就像一种数据类型,在创建类的时候指明类中方法操作的数据类型。我们直接看下面案例:
public class Animal<T> {
private T t;
public void Animal(T t){
this.t = t;
}
public T getanimal(){
return t;
}
}
public static void main(String[] args) {
Animal<Integer> a = new Animal<>(1);
String b = a;//报错,a为Integer类型
System.out.println(a);
Animal<String> str = new Animal<>("test");
System.out.println(str);
}
我们定义了Animal类中方法的操作的数据类型是T,在new Animal对象的时候指定了操作的方法为Interger或者String;更具需要指定操作的数据类型。
在接口中使用
泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中。
直接看案例
public interface a<T> {
public T test();
}
目的是要求实现必须被指定为泛型类
class b<T> implements a<T>{
@Override
public T test() {
return null;
}
}
在方法中使用
在方法中使用会比类中使用更难理解,主要有两个形式。在普通方法中使用泛型和泛型方法。
泛型方法
泛型类是在类实例化的时候指定对象操作的数据类型;泛型方法是在调用方法的时候指明方法的操作类型。
下面定义了一个泛型方法,用来指定返回类型为T。我们可以根据需要返回不同的类型。
public static <T> T getData(boolean b){
if(b){
return (T)"对";
}
else
return (T)(Integer)0;//这里不能是基本数据类型
}
String str = getData(true);
int u = getData(false);
System.out.println(str+u);
注意:泛型执行的操作类型必须为引用数据类型。
在普通方法中使用泛型
在编写类的时候还不不确定要传进取的数据类型时候,可以使用
语法:
问号是固定写法
//static void add1(List<T> t)报错。<>必须要是问号
static void add(List<?> t){
}
案例
/*代表传进去的必须是User的子类*/
static void add1(List<? extends User> t){
}
/*代表传进去的必须是User的父类*/
static void add2(List<? super Studnet> t){
}