从泛型获取ParameterizedType的类型 [英] Get Type of ParameterizedType from generic

查看:364
本文介绍了从泛型获取ParameterizedType的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法完全理解反映如何工作,所以我在尝试为 GsonBuilder 注册自定义类型适配器时遇到了一些麻烦。



我需要为 List< Something> 类型注册类型适配器。



这是一个工作代码:

  gsonBuilder.registerTypeAdapter(
New TypeToken< List< MyClass>>(){ } .getType(),新的ListDeserializer(MyClass.class)
);

事情是我有很多类来注册我的类型适配器,并且我有一个 ListDeserializer SingleDeserializer 适配器。



去通用,所以我只是调用一个函数,传递我的 GsonBuilder 和类,然后你去。



我的尝试:

  private static< T> void registerTypeAdapter(GsonBuilder gsonBuilder,T clazz){
gsonBuilder.registerTypeAdapter(clazz.getClass(),new SingleDeserializer(clazz.getClass()));
gsonBuilder.registerTypeAdapter(
New TypeToken< List< T>>(){
} .getType(),new ListDeserializer(clazz.getClass())
);

它不适用于我的 ListDeserializer code>。我的猜测是,既然 T 是一个通用的参数化类型 List ,它在运行时无法检测到它。



有什么建议?

解决方案

是的,您不能使用<$ c $在运行时,由于泛型新的TypeToken< List< T>>(){} .getType() /java/generics/erasure.htmlrel =nofollow>类型擦除。在运行时, List< T> 只是 List< Object> 。但你可以做的是创建 ParameterizedType 并使用如下所示:

  Type type = ParameterizedTypeImpl.make(List.class,new Type [] {clazz.getClass()},null); 
gsonBuilder.registerTypeAdapter(type,new ListDeserializer(clazz.getClass()));

但是你真的需要通用性吗?你可以这样做:

pre prerivate $ static $ register $ (clazz,新的SingleDeserializer());
Type type = ParameterizedTypeImpl.make(List.class,new Type [] {clazz},null);
gsonBuilder.registerTypeAdapter(type,new ListDeserializer());
}

以下是演示:

  import com.google.gson。*; 
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class Main {
public static void main(String [] args)throws Exception {
GsonBuilder gb = new GsonBuilder();
registerTypeAdapter(gb,MyClass.class);

Gson gson = gb.create();
List data = new ArrayList<>();
data.add(new MyClass(Bob));
data.add(new MyClass(Alice));

String listString = gson.toJson(data);
String soloString = gson.toJson(new MyClass(Test));

Object resultList = gson.fromJson(listString,new TypeToken< List< MyClass>>(){} .getType());
Object resultSolo = gson.fromJson(soloString,MyClass.class);

System.out.println(RESULT:);
System.out.println(FROM+ listString +TO+ resultList);
System.out.println(FROM+ soloString +TO+ resultSolo);


$ b private static void registerTypeAdapter(GsonBuilder gsonBuilder,Class<?> clazz){
gsonBuilder.registerTypeAdapter(clazz,new SingleDeserializer());
Type type = ParameterizedTypeImpl.make(List.class,new Type [] {clazz},null);
gsonBuilder.registerTypeAdapter(type,new ListDeserializer());


私有静态类ListDeserializer实现JsonDeserializer {
private static Gson gson = new Gson();
$ b $ @Override
public Object deserialize(JsonElement json,Type typeOfT,JsonDeserializationContext context)throws JsonParseException {
System.out.println(Used ListDeserializer:Type+ typeOfT);

类型t =(typeOfT instanceof ParameterizedType)?
((ParameterizedType)typeOfT).getActualTypeArguments()[0]:
Object.class;

Type type = ParameterizedTypeImpl.make(List.class,new Type [] {t},null);
List list = gson.fromJson(json,type);
返回列表;



private static class SingleDeserializer实现了JsonDeserializer {
private static Gson gson = new Gson();
$ b $ @Override
public Object deserialize(JsonElement json,Type typeOfT,JsonDeserializationContext context)throws JsonParseException {
System.out.println(Used SingleDeserializer:Type+ typeOfT);
返回gson.fromJson(json,typeOfT);



public static class MyClass {
@SerializedName(name)
private String name;

public MyClass(String name){
this.name = name;
}

public String getName(){
return name;
}

public void setName(String name){
this.name = name;
}

@Override
public String toString(){
returnMyClass {+
name ='+ name +'\ ''+
'}';
}
}
}


I cannot understand fully how reflect works, so I'm having some trouble trying to register a custom type adapter for my GsonBuilder.

I need to register a type adapter for a List<Something> type.

This is a working code:

    gsonBuilder.registerTypeAdapter(
            new TypeToken<List<MyClass>>() { }.getType(), new ListDeserializer(MyClass.class)
    );

The thing is that I have a lot of classes to register my type adapter, and I have a ListDeserializer and SingleDeserializer adapters.

I'm trying to go generic so I just call a function, pass my GsonBuilder and class, and there you go.

Here is my try:

private static <T> void registerTypeAdapter(GsonBuilder gsonBuilder, T clazz) {
    gsonBuilder.registerTypeAdapter(clazz.getClass(), new SingleDeserializer(clazz.getClass()));
    gsonBuilder.registerTypeAdapter(
            new TypeToken<List<T>>() {
            }.getType(), new ListDeserializer(clazz.getClass())
    );
}

It doesn't work for my ListDeserializer. My guess is that since T is a generic parameterized type of List, it cannot detect it at runtime.

Any suggestions?

解决方案

Yep you can't use new TypeToken<List<T>>() {}.getType() at runtime, because of generics type erasure. List<T> is just List<Object> at runtime. but what you could do is to create ParameterizedType and use something like this:

Type type = ParameterizedTypeImpl.make(List.class, new Type[]{clazz.getClass()}, null);
gsonBuilder.registerTypeAdapter(type, new ListDeserializer(clazz.getClass()) );

But do you really need genericness? You could do

private static void registerTypeAdapter2(GsonBuilder gsonBuilder, Class<?> clazz) {
    gsonBuilder.registerTypeAdapter(clazz, new SingleDeserializer());
    Type type = ParameterizedTypeImpl.make(List.class, new Type[]{clazz}, null);
    gsonBuilder.registerTypeAdapter(type, new ListDeserializer());
}

Here is demo:

import com.google.gson.*;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception {
        GsonBuilder gb = new GsonBuilder();
        registerTypeAdapter(gb, MyClass.class);

        Gson gson = gb.create();
        List data = new ArrayList<>();
        data.add(new MyClass("Bob"));
        data.add(new MyClass("Alice"));

        String listString = gson.toJson(data);
        String soloString = gson.toJson(new MyClass("Test"));

        Object resultList = gson.fromJson(listString, new TypeToken<List<MyClass>>() {}.getType());
        Object resultSolo = gson.fromJson(soloString, MyClass.class);

        System.out.println("RESULT:");
        System.out.println("FROM " + listString +" TO "+ resultList);
        System.out.println("FROM " + soloString +" TO "+ resultSolo);

    }

    private static void registerTypeAdapter(GsonBuilder gsonBuilder, Class<?> clazz) {
        gsonBuilder.registerTypeAdapter(clazz, new SingleDeserializer());
        Type type = ParameterizedTypeImpl.make(List.class, new Type[]{clazz}, null);
        gsonBuilder.registerTypeAdapter(type, new ListDeserializer());
    }

    private static class ListDeserializer implements JsonDeserializer {
        private static Gson gson = new Gson();

        @Override
        public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            System.out.println("Used ListDeserializer:  Type " + typeOfT);

            Type t = (typeOfT instanceof ParameterizedType) ?
                    ((ParameterizedType) typeOfT).getActualTypeArguments()[0] :
                    Object.class;

            Type type = ParameterizedTypeImpl.make(List.class, new Type[]{t}, null);
            List list = gson.fromJson(json, type);
            return list;
        }
    }

    private static class SingleDeserializer implements JsonDeserializer {
        private static Gson gson = new Gson();

        @Override
        public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            System.out.println("Used SingleDeserializer:  Type " + typeOfT);
            return gson.fromJson(json, typeOfT);
        }
    }

    public static class MyClass {
        @SerializedName("name")
        private String name;

        public MyClass(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "MyClass{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
}

这篇关于从泛型获取ParameterizedType的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆