先来看下 gson.fromJson 的语法:
T new Gson().fromJson(String json, Class<T> cls)
这里传入了一个 T 的的类型,可是我们已经告诉它就是要转换为 T 类型了,为什么还要传个 class 呢?
其实这个问题的来源是源于一个同事的疑问,有一天同事问我,怎么获取 T 的 class,以前在做web开发的时候,用到C#里的 typeof(T) 方法很容易就能获取到 T 的类型(我是C#转Java的,哈哈),想到Java 和 C# 语法很像,应该有类似的方法,就度娘了一通,完全没有效果,直到后来才知道原来的 Java 里的泛型和C#的实现不一样,Java 是伪泛型,那么为什么说Java是伪泛型呢?
先来看一段代码:
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("hello");
上面的代码很简单,就是Java里的最基本的泛型使用,这里的 ArrayList 传入了一个 String 类型,但是这个数组真的是 String 类型的吗,当然不是,要不也不会有上面的疑问?
再来看一段代码:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #4 // String hello
11: invokevirtual #5 // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
14: pop
15: aload_1
16: iconst_0
17: invokevirtual #6 // Method java/util/ArrayList.get:(I)Ljava/lang/Object;
20: checkcast #7 // class java/lang/String
上面这段代码是使用 javap 命令查看Java的字节码文件,很显然Java在运行时进行了类型擦除,也就是ArrayList 实际存的类型是 Object 类型,只不过在获取时做了一步强制转换(20行)。
那么Java做不了,kotlin 能实现吗?
先上代码:
// 在 kotlin中扩展 Java 类的 Gson.fromJson 方法
// 不在传入 T 的class,inline 的作用就是将函数插入到被调用处,配合 reified 就可以获取到 T 真正的类型
inline fun <reified T : Any> Gson.fromJson(json: String): T {
return Gson().fromJson(json, T::class.java)
}
// main 方法
fun main(args: Array<String>) {
var json = File("singer.json").readText()
var single: Singer = Gson().fromJson(json)
println(single)
}
// 打印信息
Singer(id=12, name=UnKnown)
哈哈,实现这个功能,在Kotlin中是不是很简单,以后这种实现交给 Kotlin 吧!