泛型系列文章(3) - 泛型高级知识 - 泛型与反射包的应用

泛型系列文章(3) - 泛型高级知识 - 泛型与反射包的应用

Gson泛型解析原理

gson官网链接

用过Gson的都知道,Gson是可以解析带复杂泛型参数的数据结构的,方式如下:

T data = new Gson().fromJson(json, new TypeToken<T>(){}.getType());
List<List<String>> data = new Gson().fromJson(json, new TypeToken<List<List<String>>>(){}.getType());

​ 我们已经知道,Class在运行期间是会擦除具体泛型信息的,因为Java代码最终会被编译为机器指令,对CPU来说,并不需要知道对象的具体类型,只要知道参与运算的对象地址就行了。如果所有的泛型信息全部存储起来,是一个很大的开销。因此,想要告诉Gson库具体的泛型类型,传递Class对象肯定是不行的。通过上面的代码我们已经可以看出来,Gson是通过传递了一个特殊的Type对象来完成这个功能的。虽然Class会擦除具体泛型信息,但是Class是会记录实现了哪些接口,继承了哪些父类的type,可以通过getGenericSuperclass获取包含泛型信息的父类信息。我们以List为例来验证下这个知识点:

//ArrayList类声明

package java.util;

public class ArrayList<E> extends AbstractList<E> implements List<E> {
	
}
List<List<String>> list = new ArrayList();
//Class不会记录自身的泛型信息
System.out.println("Class Type: " + list.getClass().getTypeName());
//Class会记录类声明时父类的泛型信息
//由于ArrayList声明时并未指定父类的具体泛型,所以获取到的就是占位符<E>
System.out.println("Superc Class Type: " + list.getClass().getGenericSuperclass().getTypeName());

/*************输出结果**************/
Class Type: java.util.ArrayList
Superc Class Type: java.util.AbstractList<E>

​ 可以看到,Class中确实保存了父类的泛型信息,不过这里的是通用占位符E,还不是具体的类型
Gson和我们的区别在于:我们是直接new了一个对象,而Gson在new后面还加上了一对大括号
大括号的作用是重写父类方法,所以new XXX() {}的本质其实于声明了一个匿名类继承XXX,然后用匿名类创建了一个对象,就相当于

class XXX extends TypeToken<List<List<String>>>

​ 如上匿名类在声明时,其实就已经指定了具体的父类泛型参数,所以在运行时是可以获取到的,我们用List来验证下:

//new后面带上大括号,表示重写父类方法,创建了一个匿名子类
List<List<String>> list = new ArrayList<List<String>>(){};
//打印对象的实际类型
System.out.println("Class Type: " + list.getClass().getTypeName());
//打印对象父类信息
System.out.println("Super Class Type: " + list.getClass().getGenericSuperclass().getTypeName());

/*************输出结果**************/
Class Type: com.easing.java.Hello$1
Super Class Type: java.util.ArrayList<java.util.List<java.lang.String>>

可以看到,通过大括号重写创建的对象,确实是子类,而且可以正确获取到实际的泛型信息。

参考链接:
https://blog.csdn.net/u013718730/article/details/106165426/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我们来一起编写一个随机点名的小程序,使用到泛型和集合框架。 首先,我们需要定义一个学生类,含学生的姓名和学号: ```java public class Student { private String name; private String id; public Student(String name, String id) { this.name = name; this.id = id; } public String getName() { return name; } public String getId() { return id; } } ``` 接下来,我们可以使用一个泛型类来表示班级,其中含了所有的学生对象: ```java import java.util.ArrayList; import java.util.List; import java.util.Random; public class Class<T extends Student> { private List<T> students; public Class() { students = new ArrayList<>(); } public void addStudent(T student) { students.add(student); } public T getRandomStudent() { Random random = new Random(); int index = random.nextInt(students.size()); return students.get(index); } } ``` 在这个泛型类中,我们使用了一个 ArrayList 来保存所有的学生对象,然后通过 getRandomStudent 方法随机返回一个学生对象。 最后,我们可以编写一个测试类来模拟随机点名的过程: ```java public class Test { public static void main(String[] args) { Class<Student> class1 = new Class<>(); class1.addStudent(new Student("张三", "001")); class1.addStudent(new Student("李四", "002")); class1.addStudent(new Student("王五", "003")); System.out.println("随机点名结果:"); Student student = class1.getRandomStudent(); System.out.println(student.getName() + " " + student.getId()); } } ``` 在这个测试类中,我们创建了一个班级对象 class1,并添加了三个学生对象。然后通过调用 getRandomStudent 方法随机返回一个学生对象,并输出其姓名和学号。 这就是一个简单的随机点名小程序,使用了泛型和集合框架来实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值