java泛型介绍使用
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?
顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),
然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,
操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
总结成一句话:泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。
1、泛型类
/**使用:
* 泛型类
* @param <T>
*/
class Test<T>{
private T data;
public Test(T data) {
this.data = data;
}
public Test() {
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Test<Integer> integerTest = new Test<>(1);
Test<String> stringTest = new Test<>("String");
定义的泛型类,就一定要传入泛型类型实参么?并不是这样,在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。
不能对确切的泛型类型使用instance of操作。如下面的操作是非法的,编译时会出错。
if(ex_num instanceof Generic<Number>){ }
2、泛型接口
/**
* 泛型接口
* @param <T>
*/
interface TestInterface<T>{
void add(T t);
T getById(String id);
void update(T t);
}
/**
* 传入泛型实参时:
* 定义一个生产器实现这个接口,虽然我们只创建了一个泛型接口Generator<T>
* 但是我们可以为T传入无数个实参,形成无数种类型的Generator接口。
* 在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型
* class TestInterfaceImpl<Shop> implements TestInterface<Shop>
* @param <Shop>
*/
class TestInterfaceImpl<Shop> implements TestInterface<Shop>{
@Override
public void add(Shop shop) {
System.out.println("add===================");
}
@Override
public Shop getById(String id) {
System.out.println("getById=====================");
return null;
}
@Override
public void update(Shop shop) {
System.out.println("update=====================");
}
}
/** 常用方式
* 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
* class TestInterfaceImpl2<T> implements TestInterface<T>
* @param <T>
*/
class TestInterfaceImpl2<T> implements TestInterface<T>{
@Override
public void add(T t) {
}
@Override
public T getById(String id) {
return null;
}
@Override
public void update(T t) {
}
}
3、泛型方法
/**
* public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
* 只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
* <T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
* 与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
* @param t
* @param <T>
*/
public static <T> void test04(T t){
System.out.println("泛型方法1===============");
}
public static <T> T test05(List<T> t){
System.out.println("泛型方法2============");
return t.get(0);
}
//边界值
public static <T extends Number> void test06(T t){
System.out.println("泛型方法3===============");
}
public static <T extends Number> void test07(Test<T> t){
System.out.println("泛型方法4===============");
}
//通配符泛型
public static void test02(List<?> t){
System.out.println("泛型方法5=================");
}
public static void tets03(Test<? extends Number> list){
System.out.println("泛型方法6");
}