1、泛型
1、定义:JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查
2、格式:<数据类型> —> 只支持引用数据类型
注:集合体系的全部接口和实现类都是支持泛型的使用
2、泛型的好处
1、统一数据类型
2、把运行时期的问题提前到了编译期,避免了强制类型转换可能出现的异常(编译阶段类型就能确定了下来)
3、泛型类
a、定义:定义类时同时定义了泛型的类,就是泛型类
b、格式:修饰符 class 类名<泛型变量>{} - - -> public class MyArrayList{}
c、作用:编译阶段可以指定数据类型,类似集合的作用
案例:模拟ArrayList集合自定义一个结合,完成添加和删除的泛型设计即可
/**
* 泛型类
*/
public class MyArrayList {
public static void main(String[] args) {
ListExample<String> list = new ListExample<>();
//根据定义泛型类,自动适应了方法中需要传递的参数类型
list.add("name");
list.delete("name");
}
}
class ListExample<E>{
public void add(E e){};
public void delete(E e){};
}
4、泛型方法
a、格式:修饰符<泛型变量> 方法返回值 方法名称(形参列表){} - - -> public void add(T t){}
b、作用:方法中可以使用泛型接受一切实际类型的参数,方法更具有通用性
c、核心思想:将出现泛型变量的地方全部转换成传输的真实数据类型
案例:给一个任意类型的数据,都能返回它的内容
/**
* 泛型方法
*/
public class GenericMethod {
public static void main(String[] args) {
Integer[] arrs = {1,2,4,5,2,5};
System.out.println(toString(arrs));
}
public static <T> String toString(T[] t){
if (t == null){
return "null";
}
if (t.length<0){
return "[]";
}
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < t.length; i++) {
sb.append(String.valueOf(t[i]));
if (i == t.length-1){
return sb.append("]").toString();
}
sb.append(",");
}
return sb.toString();
}
}
结果:[1,2,4,5,2,5]
5、泛型接口
a、格式:修饰符 interface 接口名称<泛型变量>{} - - - > public interface Data{}
b、作用:泛型接口可以让实现类选择当前功能需要操作的数据类型
c、原理:实现类可以在实现接口的时候传入自己操作的数据类型,这样重写的方法都将是针对于该类型的操作
案例:教务系统,提供一个接口可约束一定要完成数据(学生、老师)的增删改查操作
/**
* 基类1
*/
class Teacher{
}
/**
* 基类2
*/
class Car{
}
/**
* 泛型接口
* @param <E>
*/
interface Data<E> {
void add(E e);
void delete(int id);
void update(E e);
void queryById(int id);
}
/**
* 示例一
*/
public class TeacherData implements Data<Teacher>{
@Override
public void add(Teacher teacher) {
}
@Override
public void delete(int id) {
}
@Override
public void update(Teacher teacher) {
}
@Override
public void queryById(int id) {
}
}
/**
* 示例二
*/
public class CarData implements Data<Car>{
@Override
public void add(Car car) {
}
@Override
public void delete(int id) {
}
@Override
public void update(Car car) {
}
@Override
public void queryById(int id) {
}
}
6、通配符 ?
作用:可以在“使用泛型”的时候代表一切类型
案例导学:开发一个极品飞车的游戏,所有的汽车都能一起参加比赛
import java.util.ArrayList;
public class WildCard {
public static void main(String[] args) {
ArrayList<BMW> bmws = new ArrayList<>();
bmws.add(new BMW());
bmws.add(new BMW());
bmws.add(new BMW());
ArrayList<Volvo> volvos = new ArrayList<>();
volvos.add(new Volvo());
volvos.add(new Volvo());
volvos.add(new Volvo());
//使用通配符,成功将不同数据类型放入同一方法中执行
go(bmws);
go(volvos);
}
public static void go(ArrayList<?> cars){}
}
/**
* 父类
*/
class Car{}
/**
* 宝马
*/
class BMW extends Car{}
/**
* 沃尔沃
*/
class Volvo extends Car{}
7、通配符引申问题
任意的对象类型都能进入
/**
* 猫
*/
class Cat {
}
ArrayList<Cat> cats = new ArrayList<>();
cats.add(new Cat());
cats.add(new Cat());
cats.add(new Cat());
go(cats);
8、解决方案:泛型的上下限
泛型上限: ? extends Car —> ? 必须是Car或Car的子类
泛型下限: ? super Car —> ? 必须是Car或Car的父类
public static void goes(ArrayList<? extends Car> cars){}
goes(bmws);
goes(volvos);
goes(cats);//已经设置了上限,此处报错