Java 泛型

Java 泛型

需要搞个服务从 Excel 里读取数据转化为实体类,搞个泛型读取不同数据的服务按照类型实现接口就行了,但一开始没整明白。

List<?> 和 List <T>

List<?>

List<?> 是一个无限定通配符类型的列表,也被称为“类型通配符列表”,它可以包含任何类型的元素。但因为它的类型未知,无法在编译时进行类型检查。

具体使用的例子如下,首先是服务的接口,使用 List<?>,表明这个接口的实现类可以按需要返回任意类型的列表:

public interface IDataReadService {

    List<?> DataListRead(InputStream inputStream, String filename);
}

然后是这个接口的实现类,只需要重写方法并按需要写明返回的类型即可:

@Service
public class TestService implements IDataReadService{

    @Override
    public List<TestEntity> DataListRead(InputStream inputStream, String filename) {
        List<TestEntity> testList = new ArrayList<>();
	// TODO
        return testList;
    }
}

最初想到的方式,误打误撞写的也没什么问题,也算是实现了需求。

List <T>

List<T>是一个泛型类,其中的 <T> 是一个类型参数,可以被替换为任何有效的Java类型,例如 String Integer 。在编译时,编译器会对类型参数进行类型检查,并确保只有 T 类型的对象可以添加到该列表中。

区别在于,List<T> 可以容纳任何指定类型的元素,并且在编译时可以进行类型检查,而 List<?> 是一个未知类型的列表,因此无法进行编译时类型检查。 因此,在编写泛型代码时,应该尽可能使用 List<T> 来获得更好的类型安全性和可读性。 但是,在某些情况下,如果你不关心列表中的元素类型,或者你需要在代码中接受任何类型的列表,则可以使用 List<?>

就我的理解来看,它们的区别在于:List<?> 在定义后就不管后面怎么用了,反正它接受一切类;但 List<T> 在定义后,后面使用时需要指定具体的 T 类型。

使用 List<T> 改造上面的例子,首先是服务的接口:

public interface IDataReadService<T> {

    List <T> DataListRead(InputStream inputStream, String filename);
}

此处的接口定义就要加上 <T>,在使用时指定这个 T 类型,则其中的 T 类型都会被指定,实现类如下:

@Service
public class TestService implements IDataReadService<TestEntity>{

    @Override
    public List<TestEntity> DataListRead(InputStream inputStream, String filename) {
        List<TestEntity> testList = new ArrayList<>();
	// TODO
        return testList;
    }
}

相当于这个 T 是一个占位符,使用到的时候给出具体的类型,这样就可以进行类型检查了,所以才比直接用 <?> 更安全吧。

泛型的上下界

<?> 虽然是无限制类型通配符,但它也可以对接收的类型做出限制,如:

<?> // 无限制通配符
<? extends T> // 声明了类型的上界,即接收的类型可以是所指定的类型,或者是此类型的子类
<? super T> // 声明了类型的下界,即接收的类型可以是所指定的类型,或者是此类型的父类

上界

class Info<T extends Number>{    // 要求传入的类型必须是 Number 或其子类
    private T var ;        // 类型为传入的类型
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){
        return this.var.toString() ;
    }
}
public class TestExtends{
    public static void main(String args[]){
        Info<Integer> i1 = new Info<Integer>();        // 声明Integer的泛型对象
        System.out.println(i1);
    }
}

下界

class Info<T>{
    private T var ;        // 类型为传入的类型
    public void setVar(T var){
        this.var = var ;
    }
    public T getVar(){
        return this.var ;
    }
    public String toString(){
        return this.var.toString() ;
    }
}
public class TestSuper{
    public static void main(String args[]){
        Info<String> i1 = new Info<String>() ;        // 声明String的泛型对象
        Info<Object> i2 = new Info<Object>() ;        // 声明Object的泛型对象
        i1.setVar("hello") ;
        i2.setVar(new Object()) ;
        fun(i1) ;
        fun(i2) ;
    }
    public static void fun(Info<? super String> temp){    // 要求传入的必须是 String 或其父类,String 的父类只有 Object
        System.out.println(temp) ;
    }
}

部分参考:Java 全栈知识

posted @ 2023-04-24 15:17  Qirror  阅读(44)  评论(0)    收藏  举报
Live2D