泛型:可以在类或方法中预支地使用未知的类型。
泛型变量也可以理解为是一种数据类型的变量。
泛型变量的命名规则:只要符合标志符的命名规则即可,一般使用一个大写字母表示
public static void main(String[] args) {
test(12);
test("xxx"); //编译错误
}
public static void test(int i) {
System.out.println(i);
}
未引用泛型时,一个方法传入的参数必须是规定的类型
在想要传入其他类型参数时,就会报编译错误
泛型方法:
格式:
修饰符 <T> 返回值类型 方法名 (参数列表) { }
泛型方法中规定了泛型变量后,就可以在方法体中将泛型变量T 当做数据类型使用
使用了泛型方法,便可以轻松解决传入参数被规定,就无法传入其他数据类型的问题
public static void main(String[] args) {
test(12); //输出:12
test("xxx"); //输出:xxx
}
public static <T> void test(T t) {
System.out.println(t);
}
注意事项:
1.泛型变量的数据类型由调用者调用时传入的参数决定
2.泛型变量若要使用基本数据类型,要转成包装类
基本数据类型 | 包装类 |
int | Integer |
short | Short |
byte | Byte |
long | Long |
double | Double |
float | Float |
boolean | Boolean |
char | Character |
泛型类:
其实我们平时使用的Collection集合就是一个集合类
在创建集合对象的时候确定了泛型变量的数据类型,则集合中保存的元素都属于此数据类型
格式:
class 类名 <T> { }
规定泛型变量的泛型类中,可以将泛型变量T当成数据类型使用
例:
创建一个Generic泛型类:
public class Generic<T> {
public void test(T t) {
ArrayList<T> list = new ArrayList<>();
list.add(t);
System.out.println(list);
}
}
主方法创建泛型类对象:
public static void main(String[] args) {
Generic<String> g1 = new Generic<>();
Generic<Integer> g2 = new Generic<>();
g1.test("xxx"); //输出:xxx
g2.test(23); //输出:23
}
注意事项:
1.在创建泛型类对象时,指定数据类型
2.如果创建对象时没有指明泛型数据类型,则默认是Object
3.静态方法不能使用类上定义的泛型变量,除非让这个方法自己变成泛型方法
泛型接口:
在接口定义上使用了泛型变量的接口
接口中可以将泛型变量T当成一种数据类型使用
格式:
修饰符 interface 接口名 <T>{ }
1:实现接口的同时指定泛型变量的具体数据类型。(不够灵活)
创建泛型接口:
public interface Dao<T>{
public void save(T t);
public void delete(int id);
public void update(T t);
public T find(int id);
}
创建实现接口的类,并且指定泛型变量类型Student:
public class StudentDao implements Dao<Student> {
@Override
public void save(Student student) {
System.out.println("保存学生信息");
}
@Override
public void delete(int id) {
System.out.println("删除学生信息");
}
@Override
public void update(Student student) {
System.out.println("更新学生信息");
}
@Override
public Student find(int id) {
System.out.println("查询学生信息");
return null;
}
}
创建一个Student类:
public class Student { }
主方法中:
public static void main(String[] args){
Student stu = new Student();
StudentDao stuDao = new StudentDao();
stuDao.save(stu); //输出:保存学生信息
stuDao.update(stu); //输出:更新学生信息
stuDao.delete(1); //输出:删除学生信息
stuDao.find(2); //输出:查询学生信息
}
2.实现接口不指定泛型变量,由创建实现类对象时指定泛型变量(推荐)
创建一个Dao泛型接口:
public interface Dao<T>{
public void save(T t);
public void delete(int id);
public void update(T t);
public T find(int id);
}
创建一个BaseDao实现Dao泛型接口,且不指明泛型数据类型:
public class BaseDao<T> implements Dao<T> {
@Override
public void save(T t) {
System.out.println("保存" + t);
}
@Override
public void delete(int id) {
System.out.println("删除" + id);
}
@Override
public void update(T t) {
System.out.println("修改为" + t);
}
@Override
public T find(int id) {
System.out.println("查询" + id + "信息");
return null;
}
}
主方法中:
public static void main(String [] args){
BaseDao<String> bd = new BaseDao<>();
bd.delete(4); //输出:删除4
bd.find(2); //输出:查询2信息
bd.save("xxx"); //输出:保存xxx
bd.update("aaa"); //输出:修改为aaa
}
泛型的上下限:
Object ----> Number ----> Integer
父类 Object的子类 Number的子类
“?” 为泛型上下限通配符
泛型的上限:
<? extends 类> 只能接受此类和本类子类类型的数据
例:
public void print(ArrayList<? extends Number> list){ }
所以该方法仅能传入Number或Integer类型的集合到方法体中
泛型的下限:
<? super 类> 只能接受此类和本子父类类型的数据
例:
public void print(ArrayList<? super Number> list){ }
所以该方法仅能传入Object或Number类型的集合到方法体中