泛型
泛型的理解和好处
- 编译时,检查添加元素的类型,提高了安全性
- 减少了类型转换的次数,提高效率
- 不再提示编译警告
package com.bbedu.generic.improve;
import java.util.ArrayList;
public class Generic02 {
public static void main(String[] args) {
// 这样写时,ArrayList<Dog> 表示存放到集合中的元素是 Dog 类型
// 如果添加类型不满足要求,编译器会报错
// 相当于加入约束
// 在遍历时,可以直接取出 Dog 类型,而不是 Object
ArrayList<Dog> arrayList = new ArrayList<Dog>();
arrayList.add(new Dog("旺财", 10));
arrayList.add(new Dog("发财", 5));
arrayList.add(new Dog("大黄", 6));
// 放入猫
//arrayList.add(new Cat("招财猫", 3));
for (Dog dog:arrayList) {
System.out.println(dog.getName()+ "-" + dog.getAge());
}
}
}
class Dog {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Cat{
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
泛型介绍
- 泛型又称参数化类型,是 jdk5.0 出现的新特性,解决数据类型的安全性问题
- 在类声明或实例化时只要指定好需要的具体的类型即可
- Java 泛型可以保证如果程序在编译时没有翻出警告,运行时就不会产生 ClassCastException 异常,同时,代码更加简洁、健壮
- 泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型
泛型的语法
声明
interface 接口<T>{} 和 class 类<K, V>{}
说明:
- 其中,T,K,V不代表值,而是表示类型
- 任意字母都可以,常用 T 表示,short of Type
实例化
要在类名后面指定类型参数的值(类型),如:
List<String> strList = new ArrayList<String>();
Iterator<Customer> iterator = customers.iterator();
细节
interface List<T>{}, public class HashSet<E>{}...
说明:T,E只能是引用类型
- 在给泛型指定具体类型后,可以传入该类型或该类型的子类型
泛型的使用形式
List<Integer> list1 = new ArrayList<Integer>();
可简化为:// 编译器会进行类型推断,推荐这种写法:
List<Integer> list2 = new ArrayList<>();
如果是这样写:
ArrayList arrayList = new ArrayList();
等价于:
ArrayList<Object> arrayList = new ArrayList<>();
练习 p560
package com.bbedu.generic.exercise;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Objects;
public class Exercise01 {
public static void main(String[] args) {
Employee jack = new Employee("Jack", 20000, new MyDate(1999, 1, 1));
Employee jack2 = new Employee("Jack", 25000, new MyDate(1999, 1, 2));
Employee mike = new Employee("Mike", 15000, new MyDate(2000, 2, 6));
Employee sam = new Employee("Sam", 30000, new MyDate(1989, 10, 1));
Employee tim = new Employee("Tim", 10000, new MyDate(2002, 4, 1));
Employee tim2 = new Employee("Tim", 10000, new MyDate(2001, 4, 1));
ArrayList<Employee> employees = new ArrayList<>();
employees.add(sam);
employees.add(jack2);
employees.add(jack);
employees.add(mike);
employees.add(tim);
employees.add(tim2);
System.out.println("===排序前===");
System.out.println(employees);
employees.sort(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
if(!(o1 instanceof Employee && o2 instanceof Employee)){
System.out.println("类型不正确...");
return 0;
}
if(o1.getName().compareTo(o2.getName()) != 0){
return o1.getName().compareTo(o2.getName());
}
// 封装提升可维护性和复用性
return o1.getBirthday().compareTo(o2.getBirthday());
}
});
System.out.println("===排序后===");
System.out.println(employees);
}
}
class Employee {
private String name;
private double sal;
private MyDate birthday;
public Employee(String name, double sal, MyDate birthday) {
this.name = name;
this.sal = sal;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", sal=" + sal +
", birthday=" + birthday +
'}' + "\n";
}
}
class MyDate implements Comparable<MyDate>{
private int year;
private int month;
private int day;
public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyDate myDate = (MyDate) o;
return year == myDate.year && month == myDate.month && day == myDate.day;
}
@Override
public int hashCode() {
return Objects.hash(year, month, day);
}
@Override
public String toString() {
return "MyDate{" +
"year=" + year +
", month=" + month +
", day=" + day +
'}';
}
@Override
public int compareTo(MyDate o) {
int yearMinus = year - o.getYear();
if(yearMinus != 0){
return yearMinus;
}
int monthMinus = month - o.month;
if (monthMinus != 0) {
return monthMinus;
}
return day - o.day;
}
}
自定义泛型
泛型类
- 普通成员可以使用泛型(属性、方法)
- 使用泛型的数组,不能初始化
- 静态方法中不能使用类的泛型
- 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
- 如果在创建对象时,没有指定类型,默认为Object
泛型接口
- 接口中,静态成员不能使用泛型
- 泛型接口的类型,是在继承接口或者实现接口时实现的
- 没有指定类型时,默认为 Object
泛型方法
基本语法:
修饰符 <T, R> 返回方法 方法名(参数列表) {
}
- 泛型方法,可以定义在普通类中,也可以定义在泛型类中
- 当泛型方法被调用时,类型也会被确定
修饰符 返回方法 方法名(参数列表){}
不是泛型方法,是使用了泛型的方法
泛型继承和通配符
泛型没有继承机制
例如:
List
- <?>: 支持任意类型的泛型
- <? extend AA> : 表示上限,可以接收 AA 或 AA 的子类
- <? super AA>: 表示下限,可以接收 AA 或 AA 的父类
本章作业
JUnit
- 一个类有很多功能代码需要测试,为了测试,就需要写到 main 方法中
- 如果有多个功能代码测试,就需要来回注销,切换很麻烦
- 如果可以直接运行一个方法,就方便很多,并且可以给出相关信息 -> JUnit
package com.bbedu.generic.homework;
import org.junit.jupiter.api.Test;
import java.util.*;
public class Homework01 {
@Test
public void testList() {
DAO<User> dao = new DAO<>();
dao.save("001", new User(1, 10, "Jack"));
dao.save("002", new User(2, 12, "Tom"));
dao.save("003", new User(3, 14, "Mary"));
System.out.println(dao.list());
dao.update("003", new User(3, 23, "Milan"));
System.out.println(dao.list());
dao.delete("001");
System.out.println(dao.list());
System.out.println(dao.get("003"));
}
}
class DAO<T> {
private Map<String, T> map = new HashMap<>();
public T get(String id) {
return map.get(id);
}
public void update(String id, T entity) {
map.put(id, entity);
}
public List<T> list() {
List<T> list = new ArrayList<>();
Set<String> strings = map.keySet();
for (String string : strings) {
list.add(get(string));
}
return list;
}
public void delete(String id) {
map.remove(id);
}
public void save(String id, T entity) {
map.put(id, entity);
}
}
class User {
private int id;
private int age;
private String name;
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
}
评论