1.什么是泛型?
所谓泛型,就是允许在定义类、接口时通过 一个标识 表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称为类型实参)。
2.泛型的使用(为什么要有泛型)
那么为什么要有泛型呢,直接Object不是也可以存储数据吗?
- 1.解决元素存储的安全性问题,好比商品、药品标签,不会弄错。
- 2.解决获取数据元素时,需要类型强制转换的问题,好比不用每回拿商品、药品都要辨别
泛型的使用:
1.jdk 5.0新增的特性
-
2.在集合中使用泛型:
总结: -
① 集合接口或集合类在jdk5.0时都修改为带泛型的结构。
-
② 在实例化集合类时,可以指明具体的泛型类型
-
③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。
-
比如:add(E e) —>实例化以后:add(Integer e)
-
④ 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
-
⑤ 如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型。
public class GenericTest {
//在集合中使用泛型之前的情况:
@Test
public void test1(){
ArrayList list = new ArrayList();
//需求:存放学生的成绩
list.add(78);
list.add(76);
list.add(89);
list.add(88);
//问题一:类型不安全
list.add("Tom");
for(Object score : list){
//问题二:强转时,可能出现ClassCastException 强转异常
int stuScore = (Integer) score;//Tom是String类型
System.out.println(stuScore);
}
}
//在集合中使用泛型的情况:以ArrayList为例
@Test
public void test2(){
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(78);
list.add(87);
list.add(99);
list.add(65);
//编译时,就会进行类型检查,保证数据的安全
// list.add("Tom");
//方式一:
// for(Integer score : list){
// //有了泛型避免了强转操作
// int stuScore = score;
//
// System.out.println(stuScore);
//
// }
//方式二:
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
int stuScore = iterator.next();
System.out.println(stuScore);
}
}
//在集合中使用泛型的情况:以HashMap为例
@Test
public void test3(){
// Map<String,Integer> map = new HashMap<String,Integer>();
//jdk7新特性:类型推断
Map<String,Integer> map = new HashMap<>();
map.put("Tom",87);
map.put("Jerry",87);
map.put("Jack",67);
// map.put(123,"ABC");
//泛型的嵌套
Set<Map.Entry<String,Integer>> entry = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();
while(iterator.hasNext()){
Map.Entry<String, Integer> e = iterator.next();
String key = e.getKey();
Integer value = e.getValue();
System.out.println(key + "----" + value);
}
}
========================================================
集合中的自然排序:
//指明泛型时的写法
@Override
public int compareTo(Employee o) {
return this.name.compareTo(o.name);
}
//没有指明泛型时的写法
//按 name 排序
// @Override
// public int compareTo(Object o) {
// if(o instanceof Employee){
// Employee e = (Employee)o;
// return this.name.compareTo(e.name);
// }
return 0;
// throw new RuntimeException("传入的数据类型不一致!");
// }
}
---------------------------------------------------
定制排序:
TreeSet<Employee> set = new TreeSet<>(new Comparator<Employee>() {
//使用泛型以后的写法
@Override
public int compare(Employee o1, Employee o2) {
MyDate b1 = o1.getBirthday();
MyDate b2 = o2.getBirthday();
return b1.compareTo(b2);
}
//使用泛型之前的写法
//@Override
// public int compare(Object o1, Object o2) {
// if(o1 instanceof Employee && o2 instanceof Employee){
// Employee e1 = (Employee)o1;
// Employee e2 = (Employee)o2;
//
// MyDate b1 = e1.getBirthday();
// MyDate b2 = e2.getBirthday();
// //方式一:
//比较年
int minusYear = b1.getYear() - b2.getYear();
if(minusYear != 0){
return minusYear;
}
//比较月
int minusMonth = b1.getMonth() - b2.getMonth();
if(minusMonth != 0){
return minusMonth;
}
//比较日
return b1.getDay() - b2.getDay();
//
// //方式二:
// return b1.compareTo(b2);
//
// }
return 0;
// throw new RuntimeException("传入的数据类型不一致!");
// }
}