1.为什么需要泛型
1.如下:test01中集合中添加元素,不限制类型,字符串的我也能加入,数字的我也能加入,那么我想对集合中做一个取最大值操作时,就会出现异常,那么如何才能避免这个错误呢?
我们可以给类一个标识,标识这个参数的类型
泛型在ArrayList中的使用
public class CollectionMapTest {
@Test
public void test() {
List list = new ArrayList(); // ArrayList实现了List接口
list.add(67);
list.add(68);
list.add(69);
list.add(70);
// 1.问题1:类型不安全,因为add()的参数是Object类型,因为着任何类型的对象都可以添加成功
// list.add("AA");
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
// 问题2:强转可能出现问题
Integer i = (Integer)iterator.next();
int score = i;
}
}
@Test
public void test2() {
List<Integer> list = new ArrayList<>();
list.add(32);
list.add(33);
list.add(34);
list.add(35);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer i = iterator.next();
int score = i;
System.out.println(score);
}
}
}
泛型在Map中的使用
@Test
public void test3() {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Tom", 12);
map.put("Jerry", 15);
//Set<Map.Entry<String, Integer>> entries = map.entrySet();
//Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
// 上面两行的简写方式如下
var entries = map.entrySet();
var iterator = entries.iterator();
while(iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + "____" + value);
}
}
2.泛型的使用案例
1.自然排序和定制排序的使用
2.注意:TreeSet添加元素的时候需要保证是同一个类型的元素,否则会报错
3.静态方法中无法使用泛型
4.自定义异常类无法使用泛型
public class EmployeeTest {
public static void main(String[] args) {
TreeSet<Employee> set = new TreeSet<>();
Employee e1 = new Employee("LiLei", 18, new MyDate(1998, 12,28));
Employee e2 = new Employee("HanMei", 23, new MyDate(2001, 12,28));
Employee e3 = new Employee("ASh", 14, new MyDate(2006, 12,28));
Employee e4 = new Employee("sasa", 32, new MyDate(2003, 12,28));
set.add(e1);
set.add(e2);
set.add(e3);
set.add(e4);
Iterator<Employee> iterator = set.iterator();
// 1.自然排序
while (iterator.hasNext()) {
Employee employee = iterator.next();
System.out.println(employee);
}
System.out.println("---------------------------分割线-------------------------------");
// 2.按照生日排序(这里的实现方式是匿名内部类,实现了Comparator接口,并定制排序)
Comparator<Employee> comparator = new Comparator<Employee>(){
@Override
public int compare(Employee o1, Employee o2) {
int yeardistance = o1.getBirthday().getYear() - o2.getBirthday().getYear();
if (yeardistance != 0) {
return yeardistance;
}
int monthdistance = o1.getBirthday().getMonth() - o2.getBirthday().getMonth();
if (monthdistance != 0) {
return monthdistance;
}
return o1.getBirthday().getDay() - o2.getBirthday().getDay();
}
};
TreeSet<Employee> set1 = new TreeSet<>(comparator);
Employee e11 = new Employee("LiLei", 18, new MyDate(1998, 12,28));
Employee e22 = new Employee("HanMei", 23, new MyDate(2001, 12,28));
Employee e33 = new Employee("ASh", 14, new MyDate(2006, 12,28));
Employee e44 = new Employee("sasa", 32, new MyDate(2003, 12,28));
set1.add(e11);
set1.add(e22);
set1.add(e33);
set1.add(e44);
Iterator<Employee> iterator2 = set1.iterator();
while (iterator2.hasNext()) {
Employee employee = iterator2.next();
System.out.println(employee);
}
}
}
3.自定义泛型方法
形式
权限修饰符 返回值类型 方法名(形参列表) {
// 通常形参列表和返回值类型的位置会出现泛型参数T
}
泛型方法可以根据需要确定是否加static
泛型方法所属的类是否是一个泛型类(没有关系)
public <E> E method(E e) {
return null;
}
4.有限制条件的通配符的使用
- List<? extends A>: 可以将List<-A-> 或 List<-B->赋值给它,B必须是A的子类
- List<? super A>: 可以将List<-A-> 或 List<-B->赋值给它,B必须是A的父类