簡體   English   中英

如何為泛型對象調用靜態類方法?

[英]How to call the static class method for a generic object?

我需要將泛型類傳遞給類的構造函數。 類是SpiceRequestRoboSpice的Android庫來構造參考。

看起來奇怪的是,類需要將泛型類傳遞給contstructor,當它可以從泛型類本身訪問時,在這種情況下是RESULT.class ,但也許我錯了。 無論如何,我不打算改變庫的代碼,而是需要使用泛型類型的SpiceRequestMap<String, ? extends Object> SpiceRequest Map<String, ? extends Object> 這是我的代碼:

SpiceRequest<Map<String, ? extends Object>> request =
        new SpiceRequest<Map<String, ? extends Object>>(???) {
            ...
        };

SpiceRequest構造函數的簽名:

public SpiceRequest(final Class<RESULT> clazz) {
    ...
}

對於??? 我曾嘗試Map.class與編譯器錯誤: The constructor SpiceRequest<Map<String,? extends Object>>(Class<Map>) is undefined. The constructor SpiceRequest<Map<String,? extends Object>>(Class<Map>) is undefined.

Map<String, ? extends Object>.class Map<String, ? extends Object>.class給出了錯誤: Syntax error on tokens, PrimitiveType expected instead ,特別是下划線? extends Object ? extends Object 它也提供與Map.class相同的錯誤。

Map.<String, ? extends Object>class Map.<String, ? extends Object>class給出了相同的編譯器錯誤。

獲取泛型類Class<Map<String, ? extends Object>> ,?的正確方法是什么Class<Map<String, ? extends Object>> Class<Map<String, ? extends Object>>

具體參數化類型或通配符參數化類型沒有類文字。 來自Angelika Langer的泛型教程

通配符參數化類型在名為type erasure的進程中轉換為字節代碼時會丟失其類型參數。 作為類型擦除的副作用,泛型類型的所有實例化共享相同的運行時表示,即相應原始類型的表示 換句話說,參數化類型沒有自己的類型表示。 因此,沒有必要形成類文字,例如List<?>.classList<? extends Number>.class List<? extends Number>.classList<Long>.class ,因為不存在這樣的Class對象。 只有原始類型List有一個表示其運行時類型的Class對象。 它被稱為List.class

由於相同的原因,具體的參數化類型沒有類文字,簡而言之就是類型擦除

為了您的目的,您只需要對類文字進行未經檢查的強制轉換:

Class<Map<String, ?>> c = (Class<Map<String, ?>>)(Class<?>)Map.class;

請注意,通過Class<?>進行雙重轉換是必要的,因為從Class<Map>Class<Map<String, ?>>的直接轉換是非法的。

這個問題與RoboSpice本身並沒有關系,而是與Java語法的限制有關:沒有一個可以用來獲取Java中參數化泛型類的類/類型的文本。

如果你想做點什么

public class ListTweetRequest extends SpiceRequest<List<Tweet>> {

   public ListTweetRequest(Object cacheKey ) {
       super( <Here is the problem>, cacheKey );
   }
}

那么你不能將類List<Tweet>.class傳遞給你的父構造函數。 這實際上是一個Java限制,因為泛型是使用類型擦除和List<Tweet>.class在Java中沒有實際意義。

最好和最干凈的工作是使用中間類型,如:

public class ListTweet extends List<Tweet> {
}

public class ListTweetRequest extends SpiceRequest<ListTweet> {

   public ListTweetRequest(Object cacheKey ) {
       super( ListTweet.class, cacheKey );
   }
}

這樣做的好處是可以為您提供一個可以傳遞給SpiceRequest構造函數的實際類型。 但要注意混淆。 在這種情況下,proguard將嘗試刪除ListTweet類,您必須明確地保護它免於混淆。

我總是猜測擦除,但你試過用Map.class調用它嗎?

我也遇到了這個問題,我找到了像@Snicolas這樣的解決方案。

看看這個robospice-sample-retrofit的例子:

https://github.com/octo-online/RoboSpice-samples/blob/release/robospice-sample-retrofit/src/com/octo/android/robospice/sample/retrofit/network/SampleRetrofitSpiceRequest.java

實際上最好不繼承原始的List接口,而是繼承任何子類,如ArrayList等,否則你將不得不實現所有的接口方法。

import java.util.ArrayList;

public class Contributor {
    public String login;
    public int contributions;

    @SuppressWarnings("serial")
    public static class List extends ArrayList<Contributor> {
    }
}

暫無
暫無

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

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