前段时间再写SDK,需要接收服务器返回的json数据,于是定义了一个ResultDO
public class ApiResult<T> {
private int code;
private String msg;
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code =code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
对于json的处理自然用到了gson库.
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.1</version>
</dependency>
那数据如何转换呢?
public static <T>T fromJson(String json, Class<T> clz){
return (T)gson.fromJson(json, clz);
}
public static String toJson(Object obj){
return gson.toJson(obj);
}
public static <T> ApiResult<T> fromJson2(String json) {
return (ApiResult<T>) gson.fromJson(
json, new TypeToken<ApiResult<T>>(){}.getType());
}
//调用
//
// ApiResult<UserInfo> u = fromJson2(str);
如果到这里就完了,那就没有后面的纠结了。
update:用法
reference
reference
//已经有一个对象,如何在对象内添加数据。
String tmp = gson.toJson(obj);
JsonParser jp = new JsonParser();
JsonObject jj2 = (JsonObject)jp.parse(tmp);
for (String key : map.keySet())
jj2.add(key, gson.toJsonTree(map.get(key)));
System.out.println(jj2.toString());
//map 转换为 String
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("name", "xxx");
jsonObject.addProperty("value", "xxx");
Gson gson = new Gson();
String s = gson.toJson(jsonObject);
//string 转化为 map形式
String s = "{\"name\":\"xiaolin\",\"value\":\"xxx\"}";
JsonParser jp = new JsonParser();
JsonObject jo = (JsonObject)jp.parse(s);
System.out.println(jo.get("name").getAsString());
json.add(objName, gson.toJsonTree(obj));
//toJsonTree是转化为JsonElement,代表一个Json对象(子类有JsonArray JsonObject JsonNull等)。可以添加Type来使用泛型。
泛型
匿名内部类
获取泛型参数
Java泛型
Type
泛型中获得T.class
1. class
Object obj = new Object(); Object是obj的模板,obj.getClass()就是Object的模板,这个就是class类。那对于方法来说Type则是其模板。Class也继承自它。
type 是一种表示编程语言中的所有类型的类超级接口,如果 int Integer String 这都是表示一编程语言的类型,而其中的 int.class Integer.class String.class 它们表示的是类型的实例
如果,我们前面学习的反射 Class c = Integer.class Class 相当于表示类型的类,而Integer.class 则是一种
名为整形类型的类型实例
理解了上面的那些,其 理解 type 就不难了,type 与 class 一样,不过 type 是一种比 Class 表示范围不要广的
超级接口,它表示Java语言中类型的所有接口
- Type
我之前了解到的泛型是在编译器对代码进行检查,避免出错的。但是在框架中广泛用到泛型 + 反射。这样取得实际的类。这些内容在编译器也是确定的。运行时所有的泛型都是Object。
//方法1. 通过获得方法,再取得方法的类型参数,这样取得泛型的实际类型参数
import java.lang.reflect.*;
import java.util.*;
class Test {
public static void main(String args[]) throws Exception {
Method applyMethod=Test.class.getMethod("applyVector", Vector.class);
Type[] types=applyMethod.getGenericParameterTypes();
ParameterizedType pType=(ParameterizedType)types[0];
System.out.println(pType.getActualTypeArguments()[0]);
System.out.println(pType.getRawType());
}
public static void applyVector(Vector<Date> v1){ }
}
/**
输出:
class java.util.Date
class java.util.Vector
getActualTypeArguments 能取得实际类型参数,getRawType() 取得原本的类型。
*/
/**
getGenericSuperclass
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type.
对于带有泛型的class,返回一个ParameterizedType对象,对于Object、接口和原始类型返回null,对于数组class则是返回Object.class。ParameterizedType是表示带有泛型参数的类型的Java类型,JDK1.5引入了泛型之后,Java中所有的Class都实现了Type接口,ParameterizedType则是继承了Type接口,所有包含泛型的Class类都会实现这个接口
ParameterizedType是表示带有泛型参数的类型的Java类型
如 Collection<String>
方法2. 这里的匿名内部类相当于写了个继承关系,取得了其父类内容。
*/
public static void main(String[] args) {
Test<String> test = new Test<String>(){};
// 匿名内部类的声明在编译时进行,实例化在运行时进行
Type typeClass1 = test.getClass().getGenericSuperclass();
System.out.println(typeClass1);
if (typeClass1 instanceof ParameterizedType) {
Type actualType1 = ((ParameterizedType)typeClass1).getActualTypeArguments()[0];
System.out.println(actualType1);
} else {
System.out.println(typeClass1 + " is Not ParameterizedType");
}
/**
Test<java.lang.String>
class java.lang.String
*/
// 经典例子
class TClass<T> {
}
class GoodClass<T> extends TClass<String> {
public ParameterizedType getClassT() {
return (ParameterizedType) getClass().getGenericSuperclass();
}
}
class BadClass<T> extends TClass<T> {
public ParameterizedType getClassT() {
return (ParameterizedType) getClass().getGenericSuperclass();
}
}
public class GenericsTest extends TestCase {
private void print(Type[] targs) {
System.out.print("actual type arguments are:");
for (int j = 0; j < targs.length; j++) {
System.out.print(" instance of " + targs[j].getClass().getName() + ":");
System.out.println(" (" + targs[j] + ")");
}
}
public void testGoodClass() throws Exception {
ParameterizedType type = new GoodClass<Integer>().getClassT();
Type[] types = type.getActualTypeArguments();
print(types);
assertEquals(TClass.class, type.getRawType());
assertEquals(String.class, types[0]);
}
//error
public void testBadClass() throws Exception {
ParameterizedType type = new BadClass<String>().getClassT();
Type[] types = type.getActualTypeArguments();
print(types);
assertEquals(TClass.class, type.getRawType());
assertEquals(String.class, types[0]);
}
}
框架中的使用。
在父类有一个子类的对象。
/**
clazz放在了超类,也就是声明泛型的那个类的构造方法中。这样一来,子类在继承具有泛型的超类时,会自动调用超类的构造方法。在此超类的构造方法中,调用的getClass返回的是子类的Class类型
*/
class BaseDaoImpl<T> {
private Class<T> entityclass;
public BaseDaoImpl() {
try {
Class<?> clazz = getClass(); //获取实际运行的类的 Class
Type type = clazz.getGenericSuperclass(); //获取实际运行的类的直接超类的泛型类型
if(type instanceof ParameterizedType){ //如果该泛型类型是参数化类型
Type[] parameterizedType = ((ParameterizedType)type).getActualTypeArguments();//获取泛型类型的实际类型参数集
entityClass = (Class<T>) parameterizedType[0]; //取出第一个(下标为0)参数的值
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Type为: " + entityclass.getSimpleName());
}
public void save() {
System.out.println("Type为: " + entityclass.getSimpleName());
}
}
class UserDao extends BaseDaoImpl<Double>{}
class Test{
public static void main(String[] args) {
UserDao userdao=new UserDao();
userdao.save();
}
}