自定义泛型结构
# 泛型类的实例化
package com.generic;
/**
* GenericTest 就是一个普通的类
* GenericTest<E> 就是一个泛型类 这个类型现在是不确定的,相当于一个占位
* 但是确定是这个类型一定是一个引用数据类型
*
* @param <E>
*/
public class GenericTest<E> {
int age;
String name;
E sex;
public void a(E n) {
}
public void b(E[] m) {
}
}
class Test {
public static void main(String[] args) {
// 对上述类进行实例化
// 1. 实例化的时候不指定泛型 不指定类型的时候是 Object
GenericTest gt1 = new GenericTest();
gt1.a("abc");
gt1.a(17);
gt1.a(new String[]{"a", "b", "c"});
// 2. 实例化的时候指定泛型 -> 推荐方式
GenericTest<String> gt2 = new GenericTest<>();
gt2.sex = "男";
gt2.a("abc");
gt2.b(new String[]{"a", "b", "c"});
}
}
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
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
# 继承情况
父类指定泛型:
class SubGenericTest extends GenericTest<Integer> { } class Demo { public static void main(String[] args) { // 指定父类泛型,子类就不需要再指定泛型了 SubGenericTest sgt = new SubGenericTest(); sgt.a(1); } }
1
2
3
4
5
6
7
8
9
10
11父类不指定泛型:
class SubGenericTest2<E> extends GenericTest<E> { }
1
2
3如果父类不指定泛型,那么子类也会变成一个泛型,那这个 E 的类型可以在创建子类对象的时候确定。
泛型类可以定义多个参数类型
package com.generic; public class GenericDemo<A, B, C> { A age; B name; C sex; public void a(A m, B n, C x) { } }
1
2
3
4
5
6
7
8
9
10
11
12泛型类的构造器的写法
package com.generic; public class GenericDemo<A, B, C> { A age; B name; C sex; public void a(A m, B n, C x) { } // 这里不能加上泛型 public GenericDemo() { } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17不同的泛型的引用类型不可以相互赋值
泛型如果不指定,那么就会被擦除,泛型对应的类型为
Object
类型泛型类中的静态方法不能使用类的泛型
// 报错 public static int c(A a) { return 10; }
1
2
3
4static
是会优先于类和对象存在,所以这个地方会报错不能直接使用
E[]
的创建警告
A[] i = new A[10]; // 这是错误的
1提示
你可以这么写:
A[] i = (A[]) new Object[10];
1
# 带泛型的方法
提示
- 不是带泛型的方法就是泛型方法
- 泛型方法有要求:
- 这个方法的泛型的参数类型要和当前的泛型类的泛型无关
- 泛型方法对应的那个泛型参数类型 和 当前所在的这个类 是否是泛型类,泛型是啥无关
- 泛型方法定义的时候前面要加上
<T>
修饰- 原因:如果不加的话,会把
T
当做一种数据类型,然而代码和包中没有T
类型就会报错
- 原因:如果不加的话,会把
T
的类型是在调用方法的时候确定的- 泛型方法是否可以是静态方法:可以是静态方法,因为这个
T
仅仅是在调用的时候才会确定,先加载static
的时候也不会影响。
代码:
package com.generic;
public class GenericDemo<E> {
// 不是泛型方法
public void a(E e) {
// E 确定的时机是这个类实例化的时候
}
// 泛型方法
public static <T> void b(T t) {
}
}
class Demo1 {
public static void main(String[] args) {
GenericDemo<String> tg = new GenericDemo<>();
tg.a("abc");
tg.b("dwqdqw");
tg.b(true);
tg.b(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
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
# 泛型参数存在继承关系
package com.generic;
import java.util.ArrayList;
import java.util.List;
public class GenericTest01 {
public static void main(String[] args) {
Object obj = new Object();
String s = new String();
obj = s; // 多态的一种形式
Object[] objArr = new Object[10];
String[] strArr = new String[10];
objArr = strArr; // 多态的一种形式
// 泛型存在继承关系
List<Object> list1 = new ArrayList<>(); // 底层都是 Object
List<String> list2 = new ArrayList<>(); // 底层都是 Object
// list1 = list2; // 这里是不存在子类父类的基础关系的
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
提示
A 和 B 是子类父类关系,但是G<A>
和G<B>
不存在继承关系,是并列关系
# 通配符
根据上述的结论,下面的方法重载也是不可行的,相当于方法的重复定义。
警告
package com.generic;
import java.util.List;
public class GenericTest02 {
// 会报错
public void a(List<Object> list) {
}
public void a(List<String> list) {
}
public void a(List<Integer> list) {
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
引入通配符:
package com.generic;
import java.util.ArrayList;
import java.util.List;
public class Demo01 {
public static void main(String[] args) {
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<Integer> list3 = new ArrayList<>();
List<?> list = null;
list = list1;
list = list2;
list = list3;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
A 和 B 是子类父类的关系,G<A>
和G<B>
不存在子类父类的关系,但是加入了?后,G<?>
就变成了G<A>
和G<B>
的父类。
使用通配符的情况:
package com.generic;
import java.util.ArrayList;
import java.util.List;
public class GenericTest02 {
public void a(List<?> list) {
// 内部遍历的时候,用Object即可,不用?
for (Object o : list) {
System.out.println(o);
}
}
}
class Main {
public static void main(String[] args) {
GenericTest02 t = new GenericTest02();
t.a(new ArrayList<Integer>());
t.a(new ArrayList<String>());
t.a(new ArrayList<Object>());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 细节
- 内部遍历使用
Object
进行遍历 - 数据的写入操作
- 不能随意的写入操作,添加数据
- 可以
list.add(null);
但是这个没啥具体的意义
- 数据的读取操作
- 使用
Object
类型来接收数据:Object s = list.get(0);
- 使用
# 泛型受限
package com.generic;
import java.util.ArrayList;
import java.util.List;
public class Demo02 {
public static void main(String[] args) {
// a b c 三个集合是并列关系
List<Object> a = new ArrayList<>();
List<Person> b = new ArrayList<>();
List<Student> c = new ArrayList<>();
// 开始使用泛型受限: 它属于泛型的上限
/**
* 就相当于 List<Person>的父类,还是List<Person的子类>的父类
*/
List<? extends Person> list1 = null; // 此时这里对应的是 b和c 的父类
// list1 = a;
list1 = b;
list1 = c;
// 泛型的下限
/**
* 就相当于 List<Person>的父类,还是List<Person的父类>的父类
*/
List<? super Person> list2 = null;
list2 = a;
list2 = b;
// list2 = c;
}
}
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
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
编辑 (opens new window)
上次更新: 2021/11/18, 22:15:36
← 泛型 LinkedList→