簡體   English   中英

如何在運行時從泛型類型定義和運行時類型參數構建Java類型對象?

[英]How do I build a Java type object at runtime from a generic type definition and runtime type parameters?

假設泛型類型聲明(Java)

class Foo<T> {
    public T bar;
}

我怎樣才能在運行時實例化一個Type對象,該對象表示在特定類型T上參數化的Foo(也僅在運行時知道)?

我想我理解你的問題。 您希望序列化Foo<T> ,並且在運行時具有T的類對象(但在編譯時它並未修復)。 因此,在Gson中建議的創建TypeToken的匿名子類的解決方案不起作用,因為這要求參數化類型(例如Foo<String> )在編譯時被硬編碼,並且如果您使用類似Foo<T>東西它不起作用Foo<T>

但是,讓我們看一下Gson站點上的TypeToken方法實際完成了什么。 您創建一個TypeToken的匿名子類的TypeToken ,然后使用其getType()方法請求其類型參數。 類的超類是其元數據的一部分,包括其超類的泛型參數。 因此,在運行時,它可以查看自己的繼承層次結構,並找出用於TypeToken類型參數,然后返回該類型的java.lang.reflect.Type實例(如果參數化,將為ParameterizedType實例)。 獲得此Type實例后,您應該將其作為toGson()的第二個參數傳遞。

我們需要做的就是找到另一種方法來創建ParameterizedType這個實例。 ParameterizedType是一個接口,但遺憾的是,公共Java API不提供任何具體實現或任何方式來動態創建ParameterizedType 似乎有一個名為ParameterizedTypeImpl的類,在私有Sun API和您可以使用的Gson代碼中( 例如此處 )。 您只需復制代碼並將其重命名為您自己的類。 然后,要在運行時創建表示Foo<String>Type對象,您可以執行類似new ParameterizedTypeImpl(Foo.class, new Type[]{String.class}, null) (未經測試)

假設我們正在談論List<String>
你可以構造這樣的東西:

    Type type = new ParameterizedType() {
            public Type getRawType() {
                return List.class;
            }

            public Type getOwnerType() {
                return null;
            }

            public Type[] getActualTypeArguments() {
                return new Type[] { String.class};
            }
        };

如果您需要這個來從JSON反序列化,您可以使用此Type來調用gson.fromJson

類型擦除的常用方法是:

class Foo<T> {

    Class<T> clazz;

    public Foo(Class<T> c) {
        clazz = c;
    }

    public T bar {
        return clazz.newInstance();
    }
}

如果你的T沒有no-args構造函數,你可以使用Class對象的反射來做更好的事情; 一旦你有一個Class<T>的實例,你就可以獲得一個實例。

我用gson也遇到了這個問題。 我最終得到了這個:

public class JsonWrapper {
    private String className;
    private String json; // the output of the gson.toJson() method
}

當我需要反序列化時,我做了一個Class.forName(className)然后我需要調用gson庫的fromJson()方法。

我無法相信gson本身不支持這一點 - 想要做的事情似乎是一件顯而易見的事情......得到一些json並將其變成一個對象而不知道它是哪個類。

Gson確實為此提供了解決方案: https//sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Gener

當然這只是波希米亞語的解決方案(你仍需要以某種方式傳遞類型參數),但是會自動完成。

別人怎么說:)。 要實例化的類需要在運行時可用。 許多方法:將類或類名放在工廠的本地變量中,使用受保護的方法,如果需要在許多不同的地方執行此操作,則創建“對象工廠”類等。這是一種bean框架所做的工作,所以如果你正在使用它,可以通過配置它來實現。

它看起來比大多數人想象的要簡單得多:

Type collectionType = new TypeToken<ArrayList<Person>>(){}.getType();
ArrayList<Person> persons = gson.fromJson(response, collectionType);

無需將ParameterizedTypeImpl類復制為newacct建議。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM