Java泛型不兼容类型 [英] Java Generics Incompatible Types
问题描述
我有两个扩展的抽象类,以及另一个使用它们的类:
----- Base -----
public abstract class HttpRequest< RESPONSE_TYPE extends HttpResponse>
{...}
公共抽象类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)抛出IOException,HttpException,ParseException
{...}
...}
当我编译时,我得到:
错误:不兼容的类型:推理变量RESPONSE_TYPE有
不兼容的上限HttpResponse,MockyTextResponse
on
MockyTextResponse httpResponse = HttpClient.get()。synchronicRequest(new MockyTextRequest(),null);
任何想法?
$ b $
$ b
public ; 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);
工作正常
推理算法似乎无法推断 RESPONSE_TYPE
的类型。它看起来像所有三个类型参数应该由 MockyTextRequest
给出。
我并非确切地说确定为什么这是规范的情况,而是与嵌套有关。
错误可以通过以下方式重现:
//同一行上的错误
/ / C(字符串)不是推断
m(新的ArrayList< List< String>>());
//编译器能够从A
//中推理出B,而不是从A
static ,B extends List< C> ,C> void m(A a){}
这是Java 8中已解决的问题:
- Ideone Java 7编译 a>
- Ideone Java 8编译
您可以提供证人: $ c> MockyTextResponse httpResponse =
HttpClient.get()。
< MockyTextRequest,MockyTextResponse,TextWithTitle>
synchronicRequest(new MockyTextRequest(),null);
或者用几种方法来放宽类型参数:
<1>
public<
RESPONSE_TYPE扩展了HttpResponse< RESULT_TYPE> ;,
RESULT_TYPE
> RESPONSE_TYPE synchronicRequest(
final HttpRequest< RESPONSE_TYPE> httpRequest,final Object tag)
2.
public<
REQUEST_TYPE扩展了HttpRequest< RESPONSE_TYPE> ;,
RESPONSE_TYPE扩展了HttpResponse<>
> RESPONSE_TYPE synchronicRequest(
final REQUEST_TYPE httpRequest,final Object tag)
<3>
public<
REQUEST_TYPE扩展了HttpRequest< RESPONSE_TYPE> ;,
RESPONSE_TYPE扩展了HttpResponse<扩展RESULT_TYPE> ;,
RESULT_TYPE
> RESPONSE_TYPE synchronicRequest(
final REQUEST_TYPE httpRequest,final Object tag)
从您的描述看来,它似乎像#1是最好的。 (#2和#3基本上是相同的,因为 RESULT_TYPE
不会被推断出来。)
另一种方法是定义 HttpRequest
,如下所示:
class HttpRequest<
RESPONSE_TYPE扩展了HttpResponse< RESULT_TYPE> ;,
RESULT_TYPE
>
然后:
类MockyTextRequest
扩展HttpRequest< MockyTextResponse,TextWithTitle>
public<
REQUEST_TYPE扩展HttpRequest< RESPONSE_TYPE,RESULT_TYPE> ;,
RESPONSE_TYPE扩展HttpResponse< RESULT_TYPE> ;,
RESULT_TYPE
> RESPONSE_TYPE synchronicRequest(
final REQUEST_TYPE httpRequest,final Object tag)
但是这可能会导致一些您的代码更加冗长。
请注意,您应该避免使用原始类型:
// vvv
class HttpRequest< RESPONSE_TYPE extends HttpResponse<>>
I have 2 abstract classes that are extended, and another class that uses them:
-----Base-----
public abstract class HttpRequest<RESPONSE_TYPE extends HttpResponse>
{...}
public abstract class HttpResponse<DATA_TYPE>
{...}
-----Extended-----
public class MockyTextRequest extends HttpRequest<MockyTextResponse>
{...}
public class MockyTextResponse extends HttpResponse<TextWithTitle>
{...}
----Utility------
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
{...}
...}
When I compile, I get:
error: incompatible types: inference variable RESPONSE_TYPE has incompatible upper bounds HttpResponse,MockyTextResponse
on
MockyTextResponse httpResponse = HttpClient.get().synchronicRequest(new MockyTextRequest(), null);
Any Ideas?
Stange fact, this call
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)
{...}
called
HttpClient.get().request(new MockyTextRequest(), MainActivity.this);
Works ok
Full code here in github
The inference algorithm seems to not be able to infer the type of RESPONSE_TYPE
. It looks like all three type parameters should be given by MockyTextRequest
.
I'm not exactly sure why this is the case with respect to the specification but it has to do with the "nesting".
The error can be reproduced in the following way:
// 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) {}
This is the kind of thing that's been fixed in Java 8:
You could provide a witness:
MockyTextResponse httpResponse =
HttpClient.get().
<MockyTextRequest, MockyTextResponse, TextWithTitle>
synchronicRequest(new MockyTextRequest(), null);
Or a few ways to loosen up the type parameters:
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)
From your descriptions, it seems like #1 is the best. (#2 and #3 are basically the same because RESULT_TYPE
doesn't get inferred anyway.)
Another way would be to define HttpRequest
like the following:
class HttpRequest<
RESPONSE_TYPE extends HttpResponse<RESULT_TYPE>,
RESULT_TYPE
>
And then:
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)
But this probably makes some of your code a lot more verbose.
As a side note, you should avoid raw types when you can:
// vvv
class HttpRequest<RESPONSE_TYPE extends HttpResponse<?>>
这篇关于Java泛型不兼容类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!