泛型使用方法

泛型又叫参数化类型,其主要描述的是在进行类,接口,方法的定义时,使用抽象的数据结构或者进行简单的约束,其真实装载的数据结构或对象关系由开发者在创建该类,接口,方法时实现,Android开发中最典型的泛型应用就是Gson解析后端返回数据的场景。

网络请求数据解析中的泛型

假设服务器接口定义,所有接口统一返回如下的json数据:

// data为一个JsonObject
{"code":"0","message":"success","data":{}}
// data为一个JsonArray
{"code":"0","message":"success","data":[]}
复制代码

其中code代表请求的错误码,message代表接口请求信息,data代表接口返回的数据结构,那么我们可以预知到在请求多个接口时,data域中的内容也是不一样的,如果按照一般实体解析,我们每个实体类中都会有code,message这两个成员,那么有没有办法进行归一呢?这里就要用到泛型了,我们使用泛型定义上述接口返回所对应的实体如下所示:

// 泛型T代表data所对应的类型,有可能是Object,也有可能是List,具体由调用方指定
public class HttpResponse <T>{
    private String code;
    private String message;
    private  T data;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
复制代码

Gson解析使用TypeToken来指定这里泛型T的类型以完成后段返回数据解析,代码段如下:

String responseStr = response.body().string();
// 这里的String就代表data是一个字符串,对应上述实体类中的泛型T
Type type = new TypeToken<HttpResponse<String>>(){}.getType()
HttpResponse httpResponse = new Gson().fromJson(responseStr,type);
复制代码

容器类中的泛型

Java自身内部也有很多泛型声明,比如我们的各种容器类,如ArrayList,List,Collection等,Collection的定义如下所示:

public interface Collection<E> extends java.lang.Iterable<E> {

public int size();

public boolean isEmpty();

public boolean contains(@libcore.util.Nullable java.lang.Object o);

@libcore.util.NonNull public java.util.Iterator<@libcore.util.NullFromTypeParam E> iterator();

public java.lang.@libcore.util.Nullable Object @libcore.util.NonNull [] toArray();

public <T> T @libcore.util.NonNull [] toArray(T @libcore.util.NonNull [] a);

public boolean add(@libcore.util.NullFromTypeParam E e);

public boolean remove(@libcore.util.Nullable java.lang.Object o);

public boolean containsAll(@libcore.util.NonNull java.util.Collection<?> c);

public boolean addAll(@libcore.util.NonNull java.util.Collection<? extends @libcore.util.NullFromTypeParam E> c);

public boolean removeAll(@libcore.util.NonNull java.util.Collection<?> c);

public default boolean removeIf(@libcore.util.NonNull java.util.function.Predicate<? super @libcore.util.NullFromTypeParam E> filter) { throw new RuntimeException("Stub!"); }

public boolean retainAll(@libcore.util.NonNull java.util.Collection<?> c);

public void clear();

public boolean equals(@libcore.util.Nullable java.lang.Object o);

public int hashCode();

@libcore.util.NonNull public default java.util.Spliterator<@libcore.util.NullFromTypeParam E> spliterator() { throw new RuntimeException("Stub!"); }

@libcore.util.NonNull public default java.util.stream.Stream<@libcore.util.NullFromTypeParam E> stream() { throw new RuntimeException("Stub!"); }

@libcore.util.NonNull public default java.util.stream.Stream<@libcore.util.NullFromTypeParam E> parallelStream() { throw new RuntimeException("Stub!"); }
}
复制代码

从这里可以看出泛型类在被继承时,泛型数据是要发生传递的,A类中声明一个泛型T,B是A的字类,其最少也要声明一个泛型,以传递给A,确保A可以正常初始化。

架构设计中的泛型

在MVP的基础设计中,我们通过声明BaseView,BasePresenter,BaseModel,然后在其各自的子类中实现相对应的业务代码,形成一套代码规范,将一些公共逻辑封装在BaseXXX中。

但随着开发团队的人员更迭,代码量的增加,新同学在使用MVP时可能会只使用三个基类中的一个或两个,乃至搭配自己实现的其他BaseXXX类,导致业务逻辑异常,那么有没有办法形成约束,使得这三个绑定在一起使用呢?此时就需要用到泛型了。

以泛型搭建约束,实现的IBaseView,IBasePresenter,IBaseModel如下所示:

public interface IBaseView  <T extends BasePresenter>{
}
复制代码
public interface IBasePresenter <V extends BaseView,M extends BaseModel>{
}
复制代码
public interface IBaseModel {
}
复制代码

对应的Base实现类,BaseView,BasePresenter,BaseModel如下图所示

public class BaseView<P extends BasePresenter> implements IBaseView<MainPresenter> {
}
复制代码
public class BasePresenter<V extends BaseView,M extends BaseModel> implements IBasePresenter<V,M>{
}
复制代码
public class BaseModel implements IBaseModel{
}
复制代码

业务实现的View,Presenter,Model如下所示:

public class MainView extends BaseView<MainPresenter>{
}
复制代码
public class MainPresenter extends BasePresenter<MainView,MainModel>{
}
复制代码
public class MainModel extends BaseModel {
}
复制代码

从代码可以看出我们使用泛型实现了,View,Presenter,Model三者之间的持有关联依赖关系,确保其他开发者能按照我们设计的规范使用这三个类。

<?>和 < T > 有什么区别?

泛型符号 含义 备注
< T > 通配特定的一种类型,在定义时,类型确定且一致,如List strList = new ArrayList(); /
<?> 通配任意类型,假设ArrayList<?> arrays= new ArrayList();这种书写成立,那么代表arrays中可以装载任意类型的对象 /
  • <?extends E>或:表示所通配的类型为E或者E的子类型
  • <?super E>或:表示通配的类型为E或E的父类型

猜你喜欢

转载自juejin.im/post/7193231166000857149