泛指某一类型,不具体指定;在编写代码时,使用泛型占位。在使用某个类的泛型时,需填入具体的类型,才能真正的使用。
在Java中,所有的集合,都使用了泛型。
泛型的三种用法
泛型的一般用法
在类中使用泛型:
泛型在使用时指定具体的类型(List集合的原型)
//主体类
//Student类
public class Student {
private String name;
private String clazz;
private int age;
}
//Worker类
public class Worker {
private String name;
private String deptName;
private String job;
private String skill;
}
//两个主体类用“ALT+INSERT”加入有参构造方法,toString()方法,以及Getter()/Setter()方法
//在此只显示属性,不再体现占用篇幅
/**
* 团队类,使用了泛型
* @param <T> 为类型占位符,T为占用的类型名称(代指将来填入的某种类型)
* 注意:在使用Team类时,应当制定T的具体类型(必须是引用;类型);若不指定,则T默认为Object类型
*/
public class Team<T> {
//定义泛型,代指类型
private T leader;//小队的队长
private List<T> members = new ArrayList<>();//小队的其他成员
public void setLeader(T leader){
this.leader = leader;
}
public void addOneMember(T member){
members.add(member);
}
public void showMembers(){
System.out.println("当前小队的领导为:" + leader);//由于是引用类型,因此可以直接调用toString()方法,打印引用对象而非地址
for(T member : members){
System.out.println("小队成员:" + member);
}
}
}
//测试
public static void main(String[] args) {
//第一个小队,成员都是学生
//Team<>中默认为Team<Object>
Team<Student> team1 = new Team<>();
team1.setLeader(new Student("张三","1班",25));
team1.addOneMember(new Student("张三","1班",25));
team1.addOneMember(new Student("李四","1班",25));
team1.addOneMember(new Student("王五","1班",25));
team1.showMembers();
//第二小队,成员都是工人
Team<Worker> team2 = new Team<>();
team2.setLeader(new Worker("张三1","1班","项目经理","人"));
team2.addOneMember(new Worker("张三2","1班","项目经理","人"));
team2.addOneMember(new Worker("张三3","1班","项目经理","人"));
team2.addOneMember(new Worker("张三4","1班","项目经理","人"));
team2.showMembers();
}
显示结果为:
当前小队的领导为:Student{name='张三', clazz='1班', age=25}
小队成员:Student{name='张三', clazz='1班', age=25}
小队成员:Student{name='李四', clazz='1班', age=25}
小队成员:Student{name='王五', clazz='1班', age=25}
当前小队的领导为:Worker{name='张三1', deptName='1班', job='项目经理', skill='人'}
小队成员:Worker{name='张三2', deptName='1班', job='项目经理', skill='人'}
小队成员:Worker{name='张三3', deptName='1班', job='项目经理', skill='人'}
小队成员:Worker{name='张三4', deptName='1班', job='项目经理', skill='人'}
泛型的继承用法
给泛型设置一个上限:
//设置工人接口
//表示工人的行为
public interface Worker {
void doJob();
}
//设置泛型类
//Company<T extends Worker>代表上限,表示继承自Worker,不相关的类不行
public class Company<T extends Worker> {
//公司名下的所有员工
private List<T> workers = new ArrayList<>();
//公司招聘一个新员工
public void addOneWorker(T worker){
workers.add(worker);
}
//公司命令所有工人开始工作
public void allWorkersDoJob(){
for(T worker : workers){
worker.doJob();
}
}
}
//设置实现类
//司机是工人中的一种
public class Driver implements Worker{
@Override
public void doJob() {
System.out.println("我是司机,我在开车!");
}
}
//粉刷工是工人中的一种
public class Painter implements Worker{
@Override
public void doJob() {
System.out.println("我是粉刷工,我在刷墙!");
}
}
//测试
public static void main(String[] args) {
//1.第一个公司,工人全部为公司
//Company<>中指定具体类型时,要么是继承的类,要么是其子类,父类也不行
Company<Driver> taxiCompany = new Company<>();
taxiCompany.addOneWorker(new Driver());
taxiCompany.addOneWorker(new Driver());
taxiCompany.addOneWorker(new Driver());
taxiCompany.allWorkersDoJob();
//2.第二个公司,工人全部为粉刷匠
Company<Painter> painterCompany = new Company<>();
painterCompany.addOneWorker(new Painter());
painterCompany.addOneWorker(new Painter());
painterCompany.addOneWorker(new Painter());
painterCompany.allWorkersDoJob();
//错误用法:具体填入的类型Student,没有实现或继承Worker类,超出了上边界的限定
// Company<Student> studentCompany = new Company<Student>();
}
显示结果:
我是司机,我在开车!
我是司机,我在开车!
我是司机,我在开车!
我是粉刷工,我在刷墙!
我是粉刷工,我在刷墙!
我是粉刷工,我在刷墙!
方法中用泛型
/**
* 本类负责把一个对象,强制转换为子类型对象
*/
public class ObjectCaster {
/**
* 将传入的父类对象,转换为具体的子类类型返回
* 向下造型,不安全
* @param superObj 待转换的父类型对象
* @param <T> 代指返回的类型
* @return 转换后的子类对象
*/
public static <T> T cast(Object superObj){
return (T) superObj;
}
}
//测试
public static void main(String[] args) {
//创建两个子类对象,使用父类型保存
Object stuObj = new Student("小段", "软件1班", 25);
Object driverObj = new Driver();
//下面将两个父类型的引用,使用我们的“对象类型转换器”,转换为对应的子类型
//原始写法(向下造型)
//Student stu = (Student) stuObj;
//Driver driver = (Driver) driverObj;
Student stu = ObjectCaster.cast(stuObj);//本次调用cast方法时,填入的具体类型为:Student
//左侧帮助确定右侧返回的类型
Driver driver = ObjectCaster.cast(driverObj);//本次调用cast方法时,填入的具体类型为:Driver
}
应用
SSM项目中SpringIOC控制反转,方法中填入要传入的类型;
applicationContext中getBean填入类自己识别
意义
调用方法时由左侧填的类型决定右侧类型