public class Generic {
@Test
public void test() {
// 没有使用泛型之前,存储的类型是 Object
ArrayList list = new ArrayList();
}
@Test
public void test1() {
// 泛型参数为包装类 Object的子类
ArrayList list = new ArrayList();
// ArrayList list1 = new ArrayList();
list.add("Tom");
list.add("Jerry");
list.add("John");
list.add("DingJun");
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
String stuName = iterator.next();
System.out.println(stuName);
}
}
// 集合中的HashMap泛型
@Test
public void test2() {
Map map = new HashMap();
map.put("Tom",12);
map.put("Jerry",20);
map.put("John",8);
map.put("Keli",10);
// map.put(12,12);
// 泛型的嵌套
Set> entries = map.entrySet();
Iterator> iterator = entries.iterator();
while (iterator.hasNext()) {
Map.Entry next = iterator.next();
System.out.println(next.getKey() + "-----" + next.getValue());
}
}
}
2. 自定义泛型
2.1 举例
public class Order {
String orderName;
int orderId;
// 类的内部结构可以使用类的泛型
T orderT;
public Order() {};
// 以下方法都不是泛型方法
public Order(String orderName,int orderId,T orderT) {
this.orderId = orderId;
this.orderName = orderName;
this.orderT = orderT;
}
public T getOrderT() {
return orderT;
}
public void setOrderT(T orderT) {
this.orderT = orderT;
}
@Override
public String toString() {
return "Order{" +
"orderName='" + orderName + '\'' +
", orderId=" + orderId +
", orderT=" + orderT +
'}';
}
}
public class GenericTest {
@Test
public void tets() {
// 如果定义了泛型类,实例化没有指定类的泛型,则认为此泛型类型为Object类型
// 要求:建议在实例化时指明类的泛型
Order order = new Order();
order.setOrderT(123);
System.out.println(order);
order.setOrderT("Tom");
System.out.println(order);
Order order1 = new Order("OrderAA",123,"DingJun");
order.setOrderT("AA:hello");
}
}
2.2 泛型方法
泛型方法与泛型类不同的:类型参数(尖括号)是写在返回值前面的,中的 T 被称为类型参数,而方法中的T被称为参数化类型,它不是真正运行时真正的参数(被指定的类型才是真正的参数)。
声明的类型参数可以当作返回值
泛型类中的类型参数与泛型方法中的类型参数是没有联系的,泛型方法始终以自己定义的参数为准。
public class Test1 {
public T testMethod(T t) {
return t;
}
public void test1() {
Test1 test = new Test1();
System.out.println(test.testMethod("ILoveYou"));
}
}
public class OrderTest2 {
public static void main(String[] args) {
Integer[] arr = new Integer[]{1,2,3,4};
GenericTest test = new GenericTest();
List list = test.copyFromArrayToList(arr);
System.out.println(list);
}
}
class GenericTest {
public static List copyFromArrayToList(E[] arr) {
ArrayList list = new ArrayList<>();
for(E e : arr) {
list.add(e);
}
return list;
}
}
2.3 自定义泛型类泛型接口注意点
泛型可有多个参数
泛型类的构造器public GenericClass() { }
实例化后,操作原来泛型位置的结构必须与指定的泛型类型一致
泛型不同的引用不能相互赋值。
泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价于Object
泛型的指定中不能使用基本数据类型,可以使用包装类替换
静态方法中不能使用类的泛型(类声明的泛型)
异常类不可以时泛型的
不能使用new E[],但是E[] elements = (E[]) new Object[capacity]
OrderTest 类
public class OrderTest {
String orderName;
int orderId;
T orderT;
public OrderTest() {
// 创建 T 类型的数组
// 编译不通过
// T [] arr = new T[10];
// 编译通过
T[] arr =(T[]) new Object[10];
}
public void show() {
// 编译不通过
/*try{
}catch (T t) {
}*/
}
}
2.4 在继承中使用泛型
父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型
1.子类不保留父类的泛型:按需实现
没有类型擦除
具体类型
2.子类保留父类的泛型:泛型子类
全部保留
部分保留
class Father {}
// 子类不保留父类的泛型
// 1) 没有类型擦除
class Son1 extends Father {}
// 等价于class Son1 extends Father
可以在父类容器中添加子类(子类是继承的父类),而使用通配符的 List 不确定类型,所以添加写入数据时需要添加最小的类。
@Test
public void test4() {
// Person 或Person的子类
List<? extends Person> list1 = null;
List<? super Person> list2 = null;
List list3 = new ArrayList();
List list4 = new ArrayList();
List list5 = new ArrayList();
list1 = list3;
list1 = list4;
// Object 不是 Person的子类
// list1 = list5;
// list2 = list3;
list2 = list5;
list2 = list4; // Person是Student的父类
// 读取数据
list1 = list3;
// <= Person 包括Person和Person的父类, 最大的父类为Person
Person person = list1.get(0);
// 编译不通过
// Student s = list1.get(0); // 这行编译不通过,需要强转才可行
Student s = (Student) list1.get(0);
// >= Person 可能是Person的父类, 那么这里写所有类的父类Object
list2 = list4;
Object object = list2.get(0);
// 写入数据(子类 可以 赋给父类), 在父类中添加子类(因为子类是继承的父类)
// add要添加最小的类,而list1中的类是 <= Person,找不到最小的,不能赋值
// list1.add(new Student()); //编译不通过,因为list1中的对象有可能还是
// list1.add(new Object()); // Object最大,也不行
// list2中的类是 >= Person, 最小的类是Person
list2.add(new Person());
list2.add(new Student()); // Student类比Person类 还小
}
4. 泛型嵌套
外层泛型中的一个参数也是一个泛型。
public class GenericTest {
public static void main(String[] args) {
HashMap> map = new HashMap>();
ArrayList list = new ArrayList();
list.add(new Citizen("刘恺威"));
list.add(new Citizen("杨幂"));
list.add(new Citizen("小糯米"));
map.put("刘恺威",list);
Set>> entrySet = map.entrySet();
Iterator>> iterator = entrySet.iterator();
while (iterator.hasNext()) {
Map.Entry> entry = iterator.next();
String key = entry.getKey();
ArrayList value = entry.getValue();
System.out.println("户主"+key);
System.out.println("家庭成员"+value);
}
}
}
4. 作业与测试
Dao类
public class Dao {
private Map map = new HashMap();
public void save(String id,T entity) {
map.put(id,entity);
}
public T get(String id) {
// 通过key获取对象value
return map.get(id);
}
public void update(String id,T entity) {
if(map.containsKey(id)) {
map.put(id,entity);
}else {
System.out.println("map中不存在key为id的内容");
}
}
public List list() {
// 错误的
// List list = (List) map.values();
// return list;
// list是有序的, map.values()是无序的
// 子类能--->父类
// 父类 不能强转 为子类
ArrayList list = new ArrayList();
Collection values = map.values();
for(T t : values) {
list.add(t);
}
return list;
}
// 删除指定id对象
public void delete(String id) {
if(map.containsKey(id)) {
map.remove(id);
}
}
}
User
public class User {
private int id;
private int age;
private String 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;
}
public User() {
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id == user.id &&
age == user.age &&
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(id, age, name);
}
public User(int id, int age, String name) {
this.id = id;
this.age = age;
this.name = name;
}
}
DaoTest
public class DaoTest {
@Test
public void test() {
Dao dao = new Dao();
dao.save("1001",new User(1001,34,"周杰伦"));
dao.save("1002",new User(1002,20,"昆凌"));
dao.save("1003",new User(1003,25,"丁俊"));
dao.update("1003",new User(1003,30,"丁力"));
// dao.delete("1001");
List list = dao.list();
list.forEach(System.out::println);
}
}