美文网首页
Java-泛型

Java-泛型

作者: 杨0612 | 来源:发表于2020-08-31 17:11 被阅读0次
关键字:泛型、类型擦除、泛型实现、泛型缺点、泛型运用。
1.不使用泛型会怎么样?

例子1,int、String元素都可以放入list中,但在取元素的时候,需要做类型转换,如果类型不匹配,只有在运行时才知道错误,注意如果没有给List定义类型,默认是Object;

    private void test() {
        List list=new ArrayList();
        list.add(1);
        list.add("String");
        int data1= (int) list.get(0);
        String data1= (String) list.get(1);
}

例子2,Person类的data属性可以存放任意类型的数据,但在get的时候需要做类型转换,如果类型不匹配,只有在运行时才知道错误;

//定义
public class Person {    
    private Object data;    
    public void setData(Object data){
        this.data=data;
    }    
    public Object getData(){
        return this.data;
    }
}
//调用
        Person person=new Person();
        person.setData("name");
        String name= (String) person.getData();

例子1代码使用泛型,list定义为List<Integer>,只能存放Integer、int类型元素,如果放入其他类型元素,编译器类型检查会不通过,而且在获取元素时,不需要做类型转换,因为编译器已经帮我们实现了类型转换,转换成字节码就能看到。

    private void test() {
       List<Integer> list=new ArrayList();
        list.add(1);
        int data1= list.get(0);
}

例子2代码使用泛型,定义泛型T

//定义
public class Person<T> {
    private T data;
    public void setData(T data){
        this.data=data;
    }

    public T getData(){
        return this.data;
    }
}
person定义为 Person<String>类型,setData只能传入String类型参数,如果放入其他类型元素,编译器类型检查会不通过,getData也不需要做类型转换,因为编译器已经帮我们实现了类型转换;
//调用
        Person<String> person=new Person();
        person.setData("name");
        String name=person.getData();
2.泛型的好处

(1)泛型使得类型参数化,也就是把类型当成参数来使用,更具有扩展性,代码复用。列子2中,分别把Integer、String类型当成参数实例化List、Person,List即可以处理Integer类型,也能处理String,甚至自定义类型,Person同理;
(2)参数类型一旦确定,如果类型不匹配,在编译期就能发现,降低异常概率;

3.泛型实现

泛型最终也是靠Object来保存数据的,定义的泛型编译成class文件时会被擦除,这就是类型擦除。例如,List<Integer>编译时候,会将Integer擦除变成List, Person<String> 最后变成Person。虽然泛型被擦除,泛型信息还是会被保存了下来,保存在class字节码常量池中,在使用了泛型的代码处会生成一个signature签名字段指向常量池地址。

4.类型擦除优点

(1)List<Integer>变成List,这样加载到方法区,占内存就会比较小,方法区的压力也就小,而C#的泛型类型在内存中就是真实存在;
(2)Java1.5之前是使用Object,类型擦除就可以兼容之前的代码;

5.泛型缺点

(1)基本数据类型无法作为泛型实参
如果想在list中放入int类型数据,就必现把list定义成List<Integer>,那么在放入取出数据就会涉及到装箱拆箱,这样会对内存有影响(创建对象),而C#可以用基本数据类型作为泛型实参;Android推出SparseArray来替代key为Integer型的Hashmap,这样可以解决装箱拆箱问题;
(2)泛型无法用作方法重载
以下代码编译器会报错,因为类型擦除以后,这两个方法是一样的,而C#则可以;

    private void add(List<Integer> data);
    private void add(List<String> data);

(3)泛型无法当做真实类型
以下代码编译器会报错(Illegal generic type for instanceof),List<Integer> 不是一个真实类型,类型擦除以后还是List;

    private void add(List<Integer> data){
        if(data instanceof List<Integer>){            
        }
    }

以下代码编译器同样会报错(Type parameter 'T' cannot be instantiated directly),泛型T不是一个真实类型

   private <T>void a(){
       T t=new T();
    }

(4)静态方法无法引用泛型类型
以下代码编译器会报错(com.yang.memorytest.Person.this' cannot be referenced from a static context),因为泛型类型只有在类实例化的时候才确定,而静态方法可以直接通过类来调用;

public class Person<T> {    
    public static void a(T data){        
    }
}

如果静态方法需要使用泛型,可以在方法定义泛型,

public class Person {    
    public static <T>void a(T data){        
    }
}

(5)泛型的没有继承关系

public class Person<T> {
    private T data;   
}
//虽然ArrayList是List的子类
 Person<List> person=new Person<ArrayList>();
6.泛型运用-Gson

Gson提供fromJson方法将json转换成实体。虽然方法定义了<T>,但还是需要传入一个 Class<T>类型的参数,方法才能知道具体转换成什么类型,因为方法定义的T泛型最终会被类型擦除。

//调用处
ReadList.BookDetail detail = new Gson().fromJson(object.toString(), ReadList.BookDetail.class);

//源码处
  public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
    Object object = fromJson(json, (Type) classOfT);
    return Primitives.wrap(classOfT).cast(object);
  }
7.泛型运用-数据解析

通过反射获取实体类型,利用Gson进行解析。
定义抽象类CommonResultListener<T>,上层实现抽象类,并确定T泛型。CommonResultListener反射获取泛型类型,利用Gson进行解析。

以下代码,CommonResultListener实现了底层网络请求接口,网络请求成功会回调onSuccess方法,我们通过getActualTypeArguments获取泛型类型,最后通过Gson来解析数据。

public abstract class CommonResultListener<T> extends ResultListener {
    @Override
    public void onSuccess(ResultSupport resultSupport) {
            Type genericSuperclass = getClass().getGenericSuperclass();
            Type genericityType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
            try {
                String data = resultSupport.getModel("data") != null ? resultSupport.getModel("data").toString() : "";
                      T t = (new Gson()).fromJson(data, genericityType);
                    callResultSuccess(t);
            } catch (Exception e) {
                Log.e(TAG, "call back exception!", e);
            }
    }
....
总结

泛型的好处,代码复用、可扩展性以及降低异常概率;

以上分析有不对的地方,请指出,互相学习,谢谢哦!

相关文章

  • JAVA-泛型

    JAVA-泛型 sschrodinger 2018/11/15 简介 泛型是Java SE 1.5的新特性,泛型的...

  • Java-泛型

    今天记录一下Java中的泛型,毕竟大家在项目中经常用到或者看到过。参考:https://www.jianshu.c...

  • Java-泛型

    day02【Collection、泛型】 主要内容 Collection集合 迭代器 增强for 泛型 教学目标 ...

  • Java-泛型

    1、泛型概念 java 泛型,是java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被...

  • Java-泛型

    - 1.泛型定义 - 2.泛型使用 - 3.泛型上下边界 - 4.JVM如何实现的泛型?   1、定义 Jdk1....

  • Java-泛型

    关键字:泛型、类型擦除、泛型实现、泛型缺点、泛型运用。 1.不使用泛型会怎么样? 例子1,int、String元素...

  • Effective Java-泛型

    Java1.5版本中增加了泛型。在没有泛型之前,从集合中读取到的每一个对象都必须进行转换。如果不小心插入了错误类型...

  • java-泛型迷惑

    Class a = new ArrayList ().getClass(); Class b = new Arra...

  • java-泛型 擦除

    擦除的核心动机是他使得泛化的客户端可以使用非泛化的类库用来使用,反之亦然,因为java泛型不经支持向后兼容,并且现...

  • java-泛型详解

    1、概述,什么是泛型 泛型,即参数化类型 将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成...

网友评论

      本文标题:Java-泛型

      本文链接:https://www.haomeiwen.com/subject/zgdusktx.html