目录
泛型可以运用到:
1.泛型类
2.泛型方法
3.泛型接口 中
下面先用泛型类来讲解,最后在讲泛型方法和接口的语法,因为它们的定义方式和作用都是差不多的。
1.作用以及语法
1.作用:泛型,类似于C++中的函数模版
可以在定义类、方法、接口的时候不指明具体的类型
在需要调用他们的时候去确定一个任意的具体的类型。
语法:
class 泛型类的名称 <参数列表>{
//这里可以使用参数列表
}
class ClassName<T1,T2,T3>{
//这里可以使用类型参数T1,T2,T3
}
与此同时,泛型类(如上面的代码的ClassName)可以继承另一个泛型类:
class Father<T1>{
}
class ClassName<T1,T2,T3> extends Father<T1>{
//这里可以使用类型参数T1,T2,T3
}
实例化,在尖括号内可以是不同的类型,只要是类类型,以String类为例:
class Generics<T> {
public T s;
public Generics(T S) {
this.s = S;
}
@Override
public String toString() {//重写一下,等一下直接打印
return "Generics{" +
"s=" + s +
'}';
}
}
public class Test {
public static void main(String[] args) {
Generics<String> generics = new Generics("哈哈");
System.out.println(generics.s);
}
}
2.注意事项:
1.为了去规范泛型的名称<T>,一般要求要满足一下条件,在定义泛型名称时:
E 表示 Element
K 表示 Key
V 表示 Value
N 表示 Number
T 表示 Type
S, U, V 等等 - 第二、第三、第四个类型
2.尖括号内不能写基本类型,如<int>-->这是不合法的,编译器会报错:
只能写类类型:
注意上面左右两边Father后面的尖括号都要加,右边的尖括号可以不用声明类型,但是左边一定要,右边不用写的原因是:编译器会自动根据前面的类型来推导。
3.不能直接定义泛型数组,编译器会报错:
如果要定义泛型数组,需要这样写:
为什么28行的强制类型转换是不被允许的?
我们都知道,Object类是所有类的父类,但是Object[]并不是,他是一个新的类型,不是所有类型的父类,Object[]和Integer[]没有父子的从属关系,无法做到真正的强制类型转换。
3.泛型的上界
格式:
作用:
我们在开头说过,调用泛型修饰的类时可以是任意具体的类类型,既:
可以在<>内,放Integer ,也可以放String。
但是在实际开发过程中我们有时候要限制<T>内T的类型范围,这是我们就可以这样做:
运行结果:
但是如果传入尖括号的是String ,编译器会报错:
这就是泛型上界存在的意义,它可以限制泛型的边界。
注意:
泛型只有上界! 没有下界!
4.泛型方法的语法:
运行结果:
2
注意:
静态的方法需要再static后面加尖括号:
5.泛型接口的语法:
方法实现接口:
注意:一定也要在类中也声明<T>,否则编译器报错。
6.泛型的比较方式
在写程序时,我们可能会与到一些情况需要对泛型的类型进行比较,但是总会出现报错的情况:
上面的data1和data2无法直接比较,那怎么办呢?
我们可以对这个泛型类T,继承一个Comparable接口,让他们拥有比较的方法:
class Cmp<T extends Comparable<T>> {//记住两个尖括号都要加T
T data1;
T data2;
public Cmp(T A, T B) {
this.data1 = A;
this.data2 = B;
}
public T min() {
if (this.data2.compareTo(this.data2) < 0) return data1;
else return data2;
}
}
public class Test {
public static void main(String[] args) {
Cmp<Integer> Min = new Cmp<>(2, 1);
int s = Min.min();
System.out.println(s);
}
}
完