11.泛型

泛型

1.为什么需要泛型

1.不能对加入到集合ArrayList中的数据类型进行约束
2.遍历的时候,需要进行类型转换,如果集合中的数据量大,对效率有影响

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
//使用泛型来对ArrayList进行遍历
ArrayList<Dog>l1 = new ArrayList<Dog>();
dog d1 = new dog ("dog1",18);
dog d2 = new dog ("dog2",19);
dog d3 = new dog ("dog3",20);
l1.add(d1);
l1.add(d2);
l1.add(d3);
for(Dog dog:l1) {
System.out.println(dog.getname()+dog.getAge());
}
//不使用泛型:Dog-加入->Object-取出->Dog 放入到ArrayList会先转成Object,在取出时,还需要转换成Dog
//使用泛型:Dog-->Dog-->Dog 放入和取出时,不需要类型转换
class dog {
String name;
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;
}
@Override
public String toString() {
return "dog [name=" + name + ", age=" + age + "]";
}
}

2.泛型的好处

1.编译时,检查添加元素的类型,提高了安全性
2.减少了类型转换次数,提高效率

3.什么是泛型

1.广泛的类型就是泛型
2.泛型又称参数化类型,用来解决数据类型的安全性问题
3.在类声明或实例化时只要指定好需要的具体的类型即可
4.泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值类型,或者是参数类型

4.泛型语法

1
2
3
4
5
6
7
8
9
10
11
12
//泛型说明
interface 接口 <T>{ }和 class 类<K,V>{ }
//比如List,ArrayList
/*
说明:
1.其中,T,K,V不代表值,而是代表类型
2.任意字母都可以,常用T表示
*/

//泛型实例化:
List<String> strList = new ArrayList<String>();
lterator<Customer> iterator = customers.iterator();

5.泛型应用实例

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
//创建3个学生对象
//放入到HashSet中使用,要求key是String,Value是学生对象
//HashSet方式放入3个学生对象
HashSet<stu> students = new HashSet<stu>();
students.add(new stu("haozi",18));
students.add(new stu("jiaozi",16));
//遍历
for(stu s:students) {
System.out.println(s);
}

//HashMap方式放入3个学生对象
HashMap<String,stu> hm = new HashMap<String,stu>();
hm.put("1", new stu("haozi",18));
hm.put("2", new stu("jiaozi",16));
//hm.put("2", new stu("jiaozi",18));

Set<Map.Entry<String, stu>> entries = hm.entrySet();
Iterator<Map.Entry<String, stu>> iterator = entries.iterator();
while(iterator.hasNext()) {
Map.Entry<String, stu> next = iterator.next();
System.out.println(next.getKey()+next.getValue());
}
class stu{
String name;
int age;
public stu(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;
}
@Override
public String toString() {
return "stu [name=" + name + ", age=" + age + "]";
}

}

6.泛型细节

1.给泛型指向数据类型要求的是引用类型,不能是基本数据类型
2.再给泛型指定了具体类型后,可以传入该类型或者其子类的类型
3.可以简写泛型

1
List<Integer> list1 = new ArrayList<>();

4.案例

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
import java.util.*;
public class work13 {
public static void main(String[]args) {
ArrayList<Employee> al = new ArrayList<>();
al.add(new Employee("haozi2",18000,new MyDate(11,11,2000)));
al.add(new Employee("haozi2",1800,new MyDate(12,11,2000)));
al.add(new Employee("haozi3",180,new MyDate(10,10,1980)));
System.out.println(al);
al.sort(new Comparator<Employee>() {
public int compare(Employee o1,Employee o2) {
if(!(o1 instanceof Employee && o2 instanceof Employee)) {
System.out.println("类型不正确");
}
//比较name,如果name相同,则按照生日日期先后排序
int i = o1.getName().compareTo(o2.getName());
if(i!=0) {
return i;
}
//如果name相同,就比较birthday - year
int year = o1.getBirthday().getYear() - o2.getBirthday().getYear();
if(year !=0) {
return year;
}
//如果year相同,就比较month
int month = o1.getBirthday().getMonth() - o2.getBirthday().getMonth();
if(month !=0) {
return month;
}
//如果month相同,就比较day
return o1.getBirthday().getDay() - o2.getBirthday().getDay();
}
});
System.out.println();
System.out.println(al);
}
}
class Employee{
String name;
int sal;
MyDate birthday;
public Employee(String name,int 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 int getSal() {
return sal;
}
public void setSal(int sal) {
this.sal = sal;
}
public MyDate getBirthday() {
return birthday;
}
public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "\n [name=" + name + ", sal=" + sal + ", birthday=" + birthday + "]";
}

}
class MyDate{
private int month;
private int day;
private int year;
public MyDate(int month,int day,int year) {
this.month=month;
this.day=day;
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;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
@Override
public String toString() {
return "MyDate [month=" + month + ", day=" + day + ", year=" + year + "]";
}

}

7.自定义泛型类

1.语法:

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
class 类名 <T,R...>{
成员
}
/*
细节:
1.普通成员可以使用泛型(属性、方法)
2.使用泛型的数组,不能初始化
3.静态方法中不能使用类的泛型
4.泛型类的类型,是创建对象时确定的(因为创建对象时,需要指定确认类型)
5.如果在创建对象时,没有指定类型,默认为Object
*/

class Tiger<T,R,M>{
String name;
R r; //属性使用了泛型
M m;
T t;
T[] ts = new T[8]; //报错,泛型数组不能初始化,不确定T数组的数据类型
static R r2; //报错,因为静态是和类相关的,在类加载的时候对象还没有创建,所以如果静态方法和静态属性,使用了泛型,JVM就无法完成初始化
public Tiger(String name,R r,M m,T t){ //构造方法使用了泛型
this.name = name;
this.r = r;
this.m = m;
this.t = t;
}
}

/*
1.Tiger后面泛型,所以Tiger就称为自定义泛型类
2.T,R,M泛型的标识符,一般为单个字母大写,可以有多个
3.普通成员可以使用泛型(属性、方法)
4.
*/

2.自定义泛型接口

1
2
3
4
5
6
7
8
9
interface 接口名<T,R...>{

}
/*
注意细节:
1.接口中,静态成员也不能使用泛型(和泛型类规定一样)
2.泛型接口的类型,在继承接口或者实现接口时确定
3.没有指定类型,默认为Object
*/

3.自定义泛型方法

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
修饰符 <T,R...>返回类型 方法名(参数列表){

}
/*
注意细节:
1.泛型方法,可以定义在普通类中,也可以定义在泛型类中
2.当泛型方法被调用时,类型会确定
3.public void eat(E e){ },修饰符后没有<T,R..> eat
方法不是泛型方法,而是使用了泛型
*/
public static void main(String[]args){
cat c1 = new cat();
c1.fly("宝马",100); //因为是泛型,所以会自动识别传入类型
}
class car{
public void run(){ //普通方法

}
/*
说明:
1.<T,R> 就是泛型
2.是提供给fly方法使用的
*/
public <T,R> void fly(T t,R r){

}
}

4.泛型的继承和通配符

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
/*
1.泛型不具备继承性
List<Object> list = new ArrayList<String>();//错误
2.<?>:支持任意泛型类型
3.<? extends A>:支持A类以及A类的子类,规定了泛型的上限
4.<? super A>:支持A类以及A类的父亲,不限于直接父类,规定了泛型的下限
*/
//说明:List<?>表示任意的泛型类都可以接受
public static void printCollection1(List<?> c){
for(Object object:c){
System.out.println(object);
}
}

//? extends AA 表示上限,可以接收AA或者AA的子类
public static void printCollection2(List<? extends AA> c){
for(Object object:c){
System.out.println(object);
}
}

//? super 子类类名AA:支持AA类以及AA类的父亲,不限于直接父类,规定了泛型的下限
public static void printCollection2(List<? super AA> c){
for(Object object:c){
System.out.println(object);
}
}

5.案例

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
import java.util.*;
public class work1 {
public static void main(String[]args) {
DAO<User> d = new DAO<>();
d.save("1", new User(1,1000,"haozi1"));
d.save("2", new User(2,2000,"haozi2"));
d.save("3", new User(3,3000,"haozi3"));
System.out.println(d.list());
d.update("3", new User(3,5000,"haozi3"));
System.out.println(d.list());
d.delete("3");
System.out.println(d.list());
}
}
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 + "]";
}
}
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(){
List<T> list = new ArrayList<>();
Set<String> keyset = map.keySet();
for(String key:keyset) {
list.add(map.get(key));
}
return list;
}
public void delete(String id) {
map.remove(id);
}
}

11.泛型
http://example.com/2023/03/08/java/11.泛型/
作者
haozi0o0
发布于
2023年3月8日
许可协议