我学习 B站 韩顺平 老师课程的学习笔记
泛型
泛型引入
需要泛型的体现
使用代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| import java.util.ArrayList;
public class Needgenericity { public static void main(String[] args) {
ArrayList<Dog> arrayList = new ArrayList<Dog>(); arrayList.add(new Dog("小黄",10)); arrayList.add(new Dog("旺财",5)); arrayList.add(new Dog("牛狗",6)); 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;} }
|
代码说明
使用ArrayList<Dog>()
替换原本的ArrayList()
表示存放到ArrayList集合中的元素只能是Dog的对象实例
当编译器发现添加的类型不满足要求就会提前报错(不会在等到运行时再报错)
在遍历时可以直接取出Dog类型,而不是Object
原本:
1
| for(Object obj : arrayList) {...}
|
使用泛型后:
1
| for(Dog dog : arrayList) {...}
|
ArrayList的原型为:
1
| public class ArrayList<E> {...}
|
这个E称为泛型,当上面使用泛型后,那么E就全用Dog来表示了
E相当于C++的模板中的Type,声明是写就好了,可以不仅仅是E也可以是Q,A,R等任意名字,用来代表传入的类型
泛型基本介绍
- 泛型有称为参数化类型,时JDK5.0出现的新特性,解决数据类型的安全性问题
- 在类声明或实例化时只要指定好需要的具体类型即可
- java泛型可以保证如果程序在编译时没有发出警告,那么在运行时也不会产生ClassCastException异常
- java泛型也会放代码更简洁,健壮
- 泛型的作用是:可以在类声明时同时通过一个标识符表示类中的某个属性的类型,或是某个方法的返回值的类型,或者是参数模型
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public class Generic03 { public static void main(String[] args) { Person<String> Person = new Person<String>("牛人");
Person<Integer> integerPerson = new Person<Integer>(100);
} } class Person<E> { private E s;
public Person(E s) { this.s = s; } public E getS() { return s; } }
|
当然也可以有多个类型:
1 2 3
| class Person<E,T,K> { ...; }
|
泛型注意细节
假设有interface List {},public class HashSet{}…..</br>说明:T,E只能为引用类型,不能是基本类型,所以:
1 2
| List<Integer> list = new ArrayList<Integer>(); List<int> list = new ArrayList<int>();
|
在指定泛型具体类型后,可以传入该类型或该类型的子类型
泛型使用形式:
1 2
| List<Integer> list1 = new ArrayList<Integer>(); List<Integer> list2 = new ArrayList<>();
|
如果像后者一样写,看等号右边默认给它的泛型是Object,但是等号左边给定了是Integer,所以实际上泛型类型是Integer,若等号左边也没规定,就会像之前没有引入泛型一样,为默认的Object
练习(重要)
注意多看,认真看sort()写得很好,尤其是MyDate的compareTo()的封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
| import java.util.ArrayList; import java.util.Comparator; import java.util.List;
@SuppressWarnings({"all"}) public class GenericExercise { public static void main(String[] args) { List<Emp> list = new ArrayList<>(); list.add(new Emp("Smith",2500.1,new MyDate(2003,12,5))); list.add(new Emp("Smith",2500.1,new MyDate(2002,12,5))); list.add(new Emp("Rose",25000.4,new MyDate(2004,2,15))); list.add(new Emp("Jack",2503.13,new MyDate(2003,1,6))); list.sort(new Comparator<Emp>() { @Override public int compare(Emp emp, Emp t1) { if(!((emp instanceof Emp) && (t1 instanceof Emp))){ System.out.println("类型不正确"); return 0; } int i = emp.getName().compareTo(t1.getName()); if(i != 0){ return i; } return emp.getBirthday().compareTo(t1.getBirthday()); } }); System.out.println("list = " + list); } }
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 String toString() { return "MyDate{" + "year=" + year + ", month=" + month + ", day=" + day + "}"; }
@Override public int compareTo(MyDate o) { int yd =year - o.getYear(); if(yd != 0){ return yd; } int md = month - o.getMonth(); if(md != 0){ return md; } int dd; return dd = day - o.getDay(); } } class Emp { private String name; private double sal; private MyDate birthday;
public Emp(String name, double sal, MyDate birthday) { this.name = name; this.sal = sal; this.birthday = birthday; }
@Override public String toString() { return "Emp{" + "name='" + name + '\'' + ", sal=" + sal + ", birthday=" + birthday + "}\n"; }
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; } }
|
自定义泛型类
基本语法
注意细节
- 普通成员可以使用泛型
- 使用泛型的数组,不能初始化(不能new,意思是不能直接实例化,因为不知道类型,不知道开辟多大空间,避免之后空间冲突)
- 静态方法中不能使用泛型(因为静态是和类相关的,在类被加载的时候,对象都还没创建,JVM还不知道什么类型,就无法在静态方法中将类型改变为指定类型,所以JVM不能完成这样的初始化,就会报错)
- 泛型的类型,是在创建对象时就确定的(因为创建对象需要确定类型)
- 如果在创建对象时,没有指定类型,默认为Object
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
class Tiger <T,R,M> { String name; T t; R r; M m;
public void f1 (M m1) {}
public Tiger(String name, T t, R r, M m) { this.name = name; this.t = t; this.r = r; this.m = m; } public String getName() { return name; } public void setName(String name) { this.name = name; } public T getT() { return t; } public void setT(T t) { this.t = t; } public R getR() { return r; } public void setR(R r) { this.r = r; } public M getM() { return m; } public void setM(M m) { this.m = m; } }
|
自定义泛型接口
基本语法
interface 接口名 {}
注意细节
- 接口中,静态成员也不能使用泛型(这个和泛型类规定一样)
- 泛型接口的类型,在继承接口或者实现接口时确定
- 没有指定类型时,默认为Object
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| interface IUsb<U,R> { R get(U u);
void hi(R r);
void run (R r1,R r2,U u1 ,U u2);
default R method(U u){ return null; } }
class AB implements IUsb{ @Override public Object get(Object o) { return null; } @Override public void hi(Object o) {} @Override public void run(Object r1, Object r2, Object u1, Object u2) {} }
class AA implements IUsb<String, Double>{ @Override public Double get(String s) { return null; } @Override public void hi(Double aDouble) {} @Override public void run(Double r1, Double r2, String u1, String u2) {} }
interface IA extends IUsb<String, Double> {}
|
自定义泛型方法
基本语法
修饰符 返回类型 方法名(参数列表){…}
注意细节
- 泛型方法,可以定义在普通类中,也可以定义在泛型类中
- 当泛型方法被调用时,类型会确定
- 像
public void eat(E e){}
这样,修饰符后面没有,所以eat()就不是泛型方法,而是使用泛型的方法
- 一般时参数类型是什么标识符,泛型的修饰符后面就写什么标识符
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public class SelfGeneric03 { public static void main(String[] args) { Car car = new Car(); car.fly("宝马", 100); System.out.println("======="); car.fly(300, 100.1);
Fish<String, ArrayList> fish = new Fish<>(); fish.hello(new ArrayList(), 11.3f); } }
class Car {
public void run() { } public <T, R> void fly(T t, R r) { System.out.println(t.getClass()); System.out.println(r.getClass()); } }
class Fish<T, R> { public void run() { } public<U,M> void eat(U u, M m) { } public void hi(T t) { } public<K> void hello(R r, K k) { System.out.println(r.getClass()); System.out.println(k.getClass()); } }
|
泛型的继承和通配符说明
- 泛型不具备继承性
List<Object> list = new ArrayList<String>();//报错
意思是尖括号里的类型要前后一致,继承也不行
<?>:支持任意泛型类型
<? extends A>:支持A类以及A类的子类,规定了泛型的上限(为A类,比A高就不能用了)
<? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限(为A类,比A低就不能用了)
演示代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| import java.util.ArrayList; import java.util.List;
@SuppressWarnings({"all"}) public class GenericExtends { public static void main(String[] args) { Object o = new String("xx"); List<Object> list1 = new ArrayList<>(); List<String> list2 = new ArrayList<>(); List<Integer> list3 = new ArrayList<>(); List<A> list4 = new ArrayList<>(); List<B> list5 = new ArrayList<>(); List<C> list6 = new ArrayList<>(); printCollection1(list1); printCollection1(list2); printCollection1(list3); printCollection1(list4); printCollection1(list5); printCollection1(list6);
printCollection2(list4); printCollection2(list5); printCollection2(list6); printCollection3(list1);
printCollection3(list4);
} public static void printCollection1(List<?> c){ for(Object object : c){ System.out.println(object); } }
public static void printCollection2(List<? extends A> c){ for(Object object : c){ System.out.println(object); } }
public static void printCollection3(List<? super A> c){ for(Object object : c){ System.out.println(object); } } } class A{} class B extends A{} @SuppressWarnings({"unused"}) @Deprecated class C extends B{}
|
泛型进阶尝试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| import java.util.*;
public class GenericExercise01 { public static void main(String[] args) { DAO<User> userDAO = new DAO<User>(); userDAO.save("牛人", new User(123,25,"牛人")); userDAO.save("Jack", new User(125,24,"Jack")); userDAO.save("Smith", new User(133,19,"Smith")); userDAO.save("Tom", new User(159,20,"Tom")); userDAO.save("Mary", new User(115,49,"Mary"));
System.out.println("----使用get----"); System.out.println(userDAO.get("Jack")); User user = userDAO.get("Tom"); System.out.println(user);
System.out.println("----使用update----"); userDAO.update("牛人",new User(110,48,"牛人他爹")); System.out.println(userDAO.get("牛人"));
System.out.println("----使用list----"); List<User> ts = userDAO.list(); for(Object obj : ts){ System.out.println(obj); }
System.out.println("----使用delete----"); userDAO.delete("牛人"); ts = userDAO.list(); for(Object obj : ts){ System.out.println(obj); } } } class DAO<T> { private Map<String, T> map = new HashMap<>();
public void save(String id,T entity){ map.put(id,entity); } public T get(String id){ return map.get(id); } public void update(String id , T entity){ map.put(id,entity); } public List<T> list(){ ArrayList<T> ts = new ArrayList<>();
Set<String> keySet = map.keySet(); Iterator<String> iterator = keySet.iterator(); while(iterator.hasNext()){ Object o = iterator.next(); String s = (String) o; ts.add(get(s)); } return ts; } public void delete(String id){ map.remove(id); } } 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 + '\'' + '}'; } }
|