什么是泛型?
限制容器存储的元素类型,用于集合、接口、实现类中
案例1:ArrayList
ArrayList<Integer> list = new ArrayList<Integer>(); // 或省略后面的Integer ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(3);
// list.add("bb"); // 报错
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()) {
Integer i = iterator.next(); // 使用泛型,此处不再需要强转了
System.out.println(i);
}
案例2:HashMap
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("aaa", 12);
map.put("bbb", 13);
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entrySet.iterator();
while(iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
System.out.println("key:" + entry.getKey() + "\tvalue:" + entry.getValue());
}
案例3:比较器:自然/定制排序
class Person implements Comparable<Person>{
private String name;
private int age;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// ... 此处省略name、age的getter、setter方法
// ... 此处省略toString方法
public int compareTo(Person p) {
return this.age - p.getAge(); // 自然排序:按年龄从小到大排序
}
}
class Test {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("ccc", 19));
list.add(new Person("aaa", 18));
list.add(new Person("bbb", 19));
Collections.sort(list); // 自然排序
// 定制排序
Collections.sort(list, new Comparator<Person>() {
// 先比较年龄(从小到大),年龄一样时比较姓名(从小到大)
public int compare(Person p1, Person p2) {
int result = p1.getAge() - p2.getAge();
if (result != 0) {
return result;
}
return p1.getName().compareTo(p2.getName());
}
});
System.out.println(list);
}
}
自定义泛型
说明:
① 在定义类/接口时加上<T>,就表示此类/接口具备了泛型功能
② 类/接口中所有用到的泛型(T)的地方,都会替换成实例化时声明的类型
③ 当一个类继承泛型类时,泛型默认不会继承过来,所以此子类不是个泛型类(需要单独指明泛型),并且父类带泛型的属性默认是Object类型
④ 在静态方法中不能使用泛型,因为在创建对象时才能指明泛型类型
⑤ 异常类不能带泛型
class CustomTest<T> {
private int id;
private T a;
public CustomTest() {}
public CustomTest(int id, T a) {
this.id = id;
this.a = a;
}
public T getA() {
return this.a;
}
public void setA(T a) {
this.a = a;
}
}
// 情况一:直接继承,子类是不带泛型的,且继承过来的父类泛型默认是Object
class SubCustomTest1 extends CustomTest {}
// 情况二:子类不是泛型类,继承父类时,指明父类泛型的类型是Integer,所以继承过来的属性是Integer
class SubCustomTest2 extends CustomTest<Integer> {}
// 情况三:子类是个泛型,并且指明父类泛型与子类泛型相同
class SubCustomTest3<T> extends CustomTest<T> {}
// 情况四:子类是个泛型,并且指明父类泛型是Integer
class SubCustomTest4<E> extends CustomTest<Integer> {}
// 情况五:指明父类泛型是T,子类泛型是E,不冲突
class SubCustomTest5<T, E> extends CustomTest<T> {}
public class Test {
public static void main(String[] args) {
CustomTest<String> ct = new CustomTest<>();
ct.setA("123");
// ct.setA(6); // 类型不匹配,报错
System.out.println(ct.getA()); // "123"
}
}
自定义泛型方法
- 格式:
public <E> E method(E str) {}
- 说明
① 在返回值类型前面加上<E>就表示这是有一个泛型方法
② 在泛型方法调用时,指明泛型类型
③ 泛型方法可以声明static的
④ 泛型方法跟泛型类无关