泛型:用来灵活的将数据类型应用到不同的类、方法、接口中,将数据类型作为参数传递。
优点:
提供程序运行的安全性
将运行期问题转移到了编译期
省去了类型强转的麻烦
优化了程序设计
在泛型没有出来之前,用Object来接收任意类型。而在取出数据时,需要强转,这就要求程序员预知该数据类型,这显然不合理。
泛型的出现避免了Object的“任意性”,避免了程序员必须预知使用时数据类型的情况
<>里面什么都不写,叫菱形泛型,即前面是什么类型,后面也是什么类型
泛型类
/**
* 泛型类的定义
*
*/
public class Test<T> {
T t;//在类中必要的地方使用该泛型
}
你也可以这样使用
/**
* 泛型类的定义
*
*/
public class Test<T> {
//这样做的缺点是test()方法的泛型必须跟类上的泛型一致,那么我们能不能不定义类的泛型,而只让方法是个泛型方法呢?答案是能
public void test(T t){
}
}
泛型方法
/**
*
* 泛型方法的定义
* 泛型方法的泛型与所处的类无关
*/
public <T> void test(T t){
}
泛型接口:在接口上使用泛型就是泛型接口
使用方式:
1.在类实现接口的时候明确泛型
//在实现接口的时候就确定了泛型的类型
public class MyClass implements MyInterface<String> {
@Override
public void myMethod(String s) {
}
}
2.定义类的时候,不明确泛型接口的泛型类型,从而使该类也成为泛型类,在使用的时候再明确泛型
//定义MyClass的使用并不明确泛型的类型
public class MyClass<T> implements MyInterface<T> {
@Override
public void myMethod(T s) {
}
}
//使用的时候明确泛型
MyClass<String> myClass = new MyClass<>();
myClass.myMethod("大王让我来巡山");
PS:这个本质上也是泛型类的使用,只不过是类的泛型和接口的泛型是同一个
泛型通配符:<?>,用于匹配任意一种数据类型
单独介绍泛型通配符比较难以介绍清楚,我们围绕着<?>与<T>的区别来介绍
1.通配符修饰的泛型不能直接使用而<T>可以直接使用
public class MyClass<T> {
T t;//你可以作为成员变量使用T
//你也可以作为参数使用T
public void myMethod(T s) {
}
//你也可以这样直接使用T
public <T> void my(T t){
}
}
接下来我们把所有的T都换成 ?
public class MyClass<?> {
? t;
public void myMethod(? s) {
}
public <?> void my(? t){
}
}
如果你没有偷懒,你会发现你的IDE已经报错,每个使用?的地方都在报错
这就是T可以直接使用而?不可以直接使用的解释😊
2.通配符修饰相当于声明了一种变量,它可以作为参数在方法中传递,例如Collection的 containsAll()方法
使用<?>可以完成类型限定,确定数据数据边界
1.<? extends E>限定类型上限
泛型中的类型必须是E的子类
2.<? super E>限定类型下限
泛型中的类型必须是E的父类
网友评论