2015-04-12 154 views
0

我有2個抽象類是被擴展,並使用它們其他類:Java泛型類型不兼容

-----基地-----

public abstract class HttpRequest<RESPONSE_TYPE extends HttpResponse> 
{...} 
public abstract class HttpResponse<DATA_TYPE> 
{...} 

-----擴展-----

public class MockyTextRequest extends HttpRequest<MockyTextResponse> 
{...} 
public class MockyTextResponse extends HttpResponse<TextWithTitle> 
{...} 

---- ------實用

public class HttpClient 
{... 
    public <REQUEST_TYPE extends HttpRequest<RESPONSE_TYPE>, RESPONSE_TYPE extends HttpResponse<RESULT_TYPE>, RESULT_TYPE> RESPONSE_TYPE synchronicRequest(@NonNull final REQUEST_TYPE httpRequest, @Nullable final Object tag) throws IOException, HttpException, ParseException 
    {...} 
...} 

當我編譯,我得到:

error: incompatible types: inference variable RESPONSE_TYPE has incompatible upper bounds HttpResponse,MockyTextResponse

MockyTextResponse httpResponse = HttpClient.get().synchronicRequest(new MockyTextRequest(), null); 

什麼想法?


施坦格事實上,這個調用

public <REQUEST_TYPE extends HttpRequest<RESPONSE_TYPE>, RESPONSE_TYPE extends HttpResponse<RESULT_TYPE>, RESULT_TYPE> void request(@NonNull final REQUEST_TYPE httpRequest, @Nullable final Object tag, @Nullable final Listener<REQUEST_TYPE, RESPONSE_TYPE> listener) 
{...} 

稱爲

HttpClient.get().request(new MockyTextRequest(), MainActivity.this); 

這裏工作確定

全部代碼github

+0

你真的需要裏面''sychronicRequest' RESULT_TYPE'?順便問一下你在編譯什麼版本的Java? – Radiodef

+0

這是Java 7.我在函數內部使用RESULT_TYPE來避免投射 – Cheborra

+0

嗯,我可能會想出一個聰明的解決方案,但我會說不要屏住呼吸。這看起來像是一個推理錯誤,Java 7充滿了這樣的小事情。 – Radiodef

回答

2

推理算法見ms無法推斷出RESPONSE_TYPE的類型。它看起來像所有三種類型參數應該MockyTextRequest給出。

我不是究竟是當然爲什麼這是規範的情況,但它與「嵌套」有關。

錯誤可以通過以下方式複製:

// same error on this line 
// C (String) is not inferred 
m(new ArrayList<List<String>>()); 

// the compiler is able to infer B from A 
// but not C from A 
static <A extends List<B>, B extends List<C>, C> void m(A a) {} 

這是一個已經固定的Java 8中的東西類型:

可能提供證人:

MockyTextResponse httpResponse = 
    HttpClient.get(). 
     <MockyTextRequest, MockyTextResponse, TextWithTitle> 
     synchronicRequest(new MockyTextRequest(), null); 

還是有一些方法來放鬆的類型參數:

1.

public < 
    RESPONSE_TYPE extends HttpResponse<RESULT_TYPE>, 
    RESULT_TYPE 
> RESPONSE_TYPE synchronicRequest(
    final HttpRequest<RESPONSE_TYPE> httpRequest, final Object tag) 

2.

public < 
    REQUEST_TYPE extends HttpRequest<RESPONSE_TYPE>, 
    RESPONSE_TYPE extends HttpResponse<?> 
> RESPONSE_TYPE synchronicRequest(
    final REQUEST_TYPE httpRequest, final Object tag) 

3。

public < 
    REQUEST_TYPE extends HttpRequest<RESPONSE_TYPE>, 
    RESPONSE_TYPE extends HttpResponse<? extends RESULT_TYPE>, 
    RESULT_TYPE 
> RESPONSE_TYPE synchronicRequest(
    final REQUEST_TYPE httpRequest, final Object tag) 

從您的描述看,似乎#1是最好的。 (#2,#3基本上是相同的,因爲RESULT_TYPE沒有得到推斷反正。)


另一種方法是定義HttpRequest類似如下:

class HttpRequest< 
    RESPONSE_TYPE extends HttpResponse<RESULT_TYPE>, 
    RESULT_TYPE 
> 

然後:

class MockyTextRequest 
extends HttpRequest<MockyTextResponse, TextWithTitle> 

public < 
    REQUEST_TYPE extends HttpRequest<RESPONSE_TYPE, RESULT_TYPE>, 
    RESPONSE_TYPE extends HttpResponse<RESULT_TYPE>, 
    RESULT_TYPE 
> RESPONSE_TYPE synchronicRequest(
    final REQUEST_TYPE httpRequest, final Object tag) 

但是,這可能會讓你的一些代碼更加冗長。


作爲一個側面說明,你應該avoid raw types時,你可以:

//             vvv 
class HttpRequest<RESPONSE_TYPE extends HttpResponse<?>> 
+0

那麼,使用「... RESPONSE_TYPE擴展HttpResponse ...」,而不是工作,但迫使我在體內投下一些變數。 – Cheborra

+0

奇怪的是,另一個幾乎相同的函數不起作用(請參閱我的編輯) – Cheborra

+0

是的,編輯中的編譯器工作正常,因爲'RESULT_TYPE'可以從參數中推斷出來。看到我的關於嵌套的介紹評論。 – Radiodef