我的主语言是java,之后用kotlin。
最近同事有个小问题,后端传回来的json数据需要解析,但它是这样的
{
data{
part{
"key1":"5v"
"key2":"3A"
}
},
data{
part{
"key2":"1m"
"key3":"4g"
"key4":"7u"
"key5":"9p"
}
}
}
于是他就有了想法做part的时候能不能不把所有的参数都放进去
我提了2个想法,一是建立database类,所有的part类都继承;2是使用泛型
可是后来我想行不通啊,gson传参的时候要求类型是给定的,两种想法都否定了
于是我就查到一篇帖子
说kotlin的泛型和java一样是假泛型,还用C#做对比。
其中确实了一点:Gson 没有办法根据 T 直接去反序列化。
泛型这个东西别称是‘参数化类型’,就是把一个确定的类型参数化了,变为不确定,在调用时传入具体类型。
操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
比如List就是经典使用,他的目的是在编译期检查出ClassCastException,防止运行时崩溃
而java在编译期后就开始去泛型化
说到泛型就不得不提通配符,当你的List中想包含父类和子类,纯泛型就做不到了,你就得用通配符
Generic<?> obj 可以放入任意类型的对象
然而这样还是有毛病,ClassCastException异常怎么办?
那就需要
Generic<? extends E> obj//也称泛型上下边界
相对于泛型类来说,泛型方法稍微麻烦一点的
//在方法中使用了泛型,但并不是一个泛型方法,这只是类中一个普通的成员方法,只不过他的返回值是在声明泛型类已经声明过的泛型。
//所以在这个方法中才可以继续使用 T 这个泛型。
public T getKey(){
return key;
}
/**泛型方法的基本介绍
* @param tClass 传入的泛型实参
* @return T 返回值为T类型
* 说明:
* 1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
* 2)与泛型类的定义一样,<T>后面的T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
* 3)Class<T>表明函数的传参tClass的类型为T,但相同的T表示的类可以不同
* 4)静态方法
*/
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
IllegalAccessException{
T instance = tClass.newInstance();
return instance;
}
/**
* 这才是一个真正的泛型方法。
* 首先在public与返回值之间的<T>必不可少,这表明这是一个泛型方法,并且声明了一个泛型T
* 这个T可以出现在这个泛型方法的任意位置.
* 泛型的数量也可以为任意多个 */
public <T,K> K showKeyName(Generic<T> container){
}
/*此泛型方法使用泛型E,泛型E可以为任意类型,可以和类型T相同,也可以不同。
由于泛型方法在声明的时候会声明泛型<E>,
因此即使在泛型类中并未声明泛型,
编译器也能够正确识别泛型方法中识别的泛型。
*/
public <E> void show_3(E t){
System.out.println(t.toString());
}
/*使用泛型的静态方法
静态方法无法访问类上定义的泛型;
如果静态方法要使用泛型,必须将静态方法也定义成泛型方法
*/
public static <T> void show(T t){
}
Object obj = genericMethod(Class.forName("com.test.test"));
我这里直接引用了博客里的段落
需要注意使用泛型的静态方法只能是泛型方法,public static void show(T t){..},这种编译器会提示错误信息:
“StaticGenerator cannot be refrenced from static context”
另外注释:
在java中是”不能创建一个确切的泛型类型的数组”的。
这句话是说你可以创建带通配符的泛型类型数组
//也就是说下面的这个例子是不可以的:
List<String>[] ls = new ArrayList<String>[10];
//而使用通配符创建泛型数组是可以的,对于通配符的方式,最后取出数据是要做显式的类型转换的。
List<?>[] ls = new ArrayList<?>[10];
//这样也是可以的:
List<String>[] ls = new ArrayList[10];
也就是说泛型类型数组,要么类型为通配符,要么实例化时省略类型