一、泛型的上界
class Myclass<类型参数 extends 类型上界> {
}
1
2
3
类型的上界决定了泛型的范围。
class MyArray {
}
public static void main(String[] args) {
MyArray<Integer> myArray = new MyArray<>();
MyArray<Boolean> myArray1 = new MyArray<Boolean>();
}
1
2
3
4
5
6
7
我们发现指定了泛型的上界为数值类Number时,传入Boolean类型就会报错。
如果没有指定类型的边界,可以认可 T extends Object,当指定了某个类型为上界,那么只接受某类型本身和子类型作为E的类型实参
上界为接口
我们要实现一个类去找数组的一个的最大值
这里报错了,因为我们这里是Object类型,如果是类型实参是对象的话不就能这样比较了,所以我们将上界定为Comparable接口。
class MyArray> {
public T findMax(T[] arr) {
T max = arr[0];
for (int i = 1; i < arr.length - 1; i++) {
if (arr[i].compareTo(max) > 0) {
max = arr[i];
}
}
return max;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
我们来求一个Integer类型的最大值。
public static void main(String[] args) {
MyArray<Integer> myArray = new MyArray<>();
Integer[] arr = {1,4,6,3,2};
System.out.println(myArray.findMax(arr));
}
1
2
3
4
5
我们来求一个Person类的最大值。
我们发现使用Person作为类型实参,未法创建对象,因为我们将泛型上界设置为了实现了Comparable的类类型。
class Person implements Comparable{
public int age;
public Person(int age) {
this.age = age;
}
@Override
public int compareTo(Person o) {
return this.age - o.age;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
public static void main(String[] args) {
MyArray<Person> myArray = new MyArray<>();
Person[] per = {new Person(15),new Person(18),new Person(20)};
System.out.println(myArray.findMax(per));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
二、泛型方法
1 静态方法
刚刚我们实现的求某个类型数组的最大值必须得创建一个对象,那我们可以不创建对象直接调用吗?
我们直接给方法加上static时,系统报错了,因为static方法是在类加载指定,擦除机制是在编译时检查和强制转换,在类加载时,并不知道是什么类型,所以不能直接加static。
静态方法语法:
public static<泛型形参> T findMax(T[] arr)
1
class MyArray {
public static<T extends Comparable<T>> T findMax(T[] arr) {
T max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i].compareTo(max) > 0) {
max = arr[i];
}
}
return max;
}
}
public static void main(String[] args) {
Integer[] arr = {1,5,4,7,9,2};
Integer max = MyArray.findMax(arr);
System.out.println(max);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
这样我们就可以不依赖对象求出最大值了,那类型实参在那里传?
一般在引用点的后面,一般可以省略。
2 普通方法
静态方法语法:
public <泛型形参> T findMax(T[] arr)
1
class MyArray {
public <T extends Comparable<T>> T findMax(T[] arr) {
T max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i].compareTo(max) > 0) {
max = arr[i];
}
}
return max;
}
}
public static void main(String[] args) {
Integer[] arr = {1,5,4,7,9,2};
MyArray myArray = new MyArray();
System.out.println(myArray.findMax(arr));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
三、通配符
什么是通配符:? 用于在泛型的使用
1 通配符的引入
class Data {
public T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
public static void main(String[] args) {
Data<Integer> data = new Data<>();
data.setData(18);
print(data);
}
public static void print(Data<Integer> data) {
System.out.println(data.getData());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
如果我们想输入类型实参为String类型呢?重写一个方法吗?支持重载吗?
我们当写入两种不同泛型类型的方法时,系统报错了,因为在运行阶段是没有泛型这个概念的,相当于他们的类型都是Data类型。
我们来验证一下,打印两种不同泛型实参类型的对象:
public static void main(String[] args) {
Data<Integer> data = new Data<>();
Data<String> data1 = new Data<>();
System.out.println(data);
System.out.println(data1);
}
1
2
3
4
5
6
我们发现打印出来对象的类型是一样的。