抱歉标题太差。如果能帮我想一个更好的标题就好了,但我甚至不知道该如何描述我的问题。
假设我有以下类型。
interface M<K, V> {}
interface F<I, O> {}
假设我创建了一个实现这两个接口的类。
record A<A1, A2> (A1 a1, A2 a2)
implements
M<A1, A2>,
F<A1, A2>
{}
好的,太棒了。现在我可以A
在任何地方使用M
或 了F
。
现在我的问题来了。我尝试执行以下操作,但因编译器错误而失败。
public class DoublyNestedGenerics
{
interface M<K, V> {}
interface F<I, O> {}
record A <A1, A2> (A1 a1, A2 a2)
implements
M<A1, A2>,
F<A1, A2>
{}
private
static
<
D1,
D2,
D extends
M<D1, D2>
& F<D1, D2>
>
D
canItWork(final D1 d1, final D2 d2)
{
// return new A(d1, d2);
throw new UnsupportedOperationException();
}
}
好的,一切都编译通过了。但是,如果我取消注释返回并替换异常,则会收到以下编译错误。
DoublyNestedGenerics.java:28: warning: [rawtypes] found raw type: A
return new A(d1, d2);
^
missing type arguments for generic class A<A1,A2>
where A1,A2 are type-variables:
A1 extends Object declared in record A
A2 extends Object declared in record A
好的,说得通。让我将返回值改为这样。
return new A<>(d1, d2);
按下编译按钮会出现以下编译器错误。
DoublyNestedGenerics.java:28: error: incompatible types: cannot infer type arguments for A<>
return new A<>(d1, d2);
^
reason: no instance(s) of type variable(s) A1,A2 exist so that A<A1,A2> conforms to D
where A1,A2,D,D1,D2 are type-variables:
A1 extends Object declared in record A
A2 extends Object declared in record A
D extends M<D1,D2>,F<D1,D2> declared in method <D1,D2,D>canItWork(D1,D2)
D1 extends Object declared in method <D1,D2,D>canItWork(D1,D2)
D2 extends Object declared in method <D1,D2,D>canItWork(D1,D2)
1 error
我没有完全理解这个错误,所以我决定简化这个问题。
我改变了方法,改为使用一些硬编码类型,而不仅仅是D1
和D2
。新方法如下所示。
private
static
<
D extends
M<Integer, Integer>
& F<Integer, Integer>
>
D
canItWorkAttempt2(final Integer d1, final Integer d2)
{
// return new A<>(d1, d2);
throw new UnsupportedOperationException();
}
交换注释并按编译后出现以下编译器错误。
DoublyNestedGenerics.java:44: error: incompatible types: cannot infer type arguments for A<>
return new A<>(d1, d2);
^
reason: no instance(s) of type variable(s) A1,A2 exist so that A<A1,A2> conforms to D
where A1,A2,D are type-variables:
A1 extends Object declared in record A
A2 extends Object declared in record A
D extends M<Integer,Integer>,F<Integer,Integer> declared in method <D>canItWorkAttempt2(Integer,Integer)
1 error
好的,小得多,因此更容易解析。
让我印象深刻的一件事是它说A1 extends Object declared in record A
。
嗯,不对——应该是Integer
,而不是Object
。也许推理需要一些帮助。所以我把返回值改成了这个。
return new A<Integer, Integer>(d1, d2);
这导致了以下编译器错误。
DoublyNestedGenerics.java:44: error: incompatible types: A<Integer,Integer> cannot be converted to D
return new A<Integer, Integer>(d1, d2);
^
where D is a type-variable:
D extends M<Integer,Integer>,F<Integer,Integer> declared in method <D>canItWorkAttempt2(Integer,Integer)
1 error
进展!我现在开始有了怀疑,为了证实这些怀疑,我决定大大简化我的问题。我创建了以下类。
record N (Integer n1, Integer n2)
implements
M<Integer, Integer>,
F<Integer, Integer>
{}
编译没有问题。很好,让我们尝试更改返回类型以改用此类型。这是我将返回更改为的内容。
return new N(d1, d2);
满怀希望,我按下了编译按钮。
DoublyNestedGenerics.java:50: error: incompatible types: N cannot be converted to D
return new N(d1, d2);
^
where D is a type-variable:
D extends M<Integer,Integer>,F<Integer,Integer> declared in method <D>canItWorkAttempt2(Integer,Integer)
1 error
非常令人失望。但我发现了其他问题。错误信息中显示where D is a type-variable: D extends M<Integer,Integer>,F<Integer,Integer>
。
他们使用了extends这个词。无奈之下,我尝试添加以下类型。
interface C<C1, C2> extends M<C1, C2>, F<C1, C2> {}
record N2 (Integer n1, Integer n2) implements C<Integer, Integer> {}
然后,从那时起,我改变了我的回报,这样说。
final C<Integer, Integer> blah = new N2(d1, d2);
return blah;
然后我按下了编译。
DoublyNestedGenerics.java:55: error: incompatible types: C<Integer,Integer> cannot be converted to D
return blah;
^
where D is a type-variable:
D extends M<Integer,Integer>,F<Integer,Integer> declared in method <D>canItWorkAttempt2(Integer,Integer)
1 error
这时候,我心里很烦躁。
错误消息以某种方式告诉我C<Integer,Integer> cannot be converted to D
。它还告诉我D is a type-variable
,具体来说,D extends M<Integer,Integer>,F<Integer,Integer>
这正是 C 所做的。但是,它仍然不起作用?
这让我想到了这里。我遗漏了什么?如果有人愿意提出建议,我再次希望有人能帮我起草一个更好的标题。
最后,这里是完整的代码,以防难以理解。
public class DoublyNestedGenerics
{
interface M<K, V> {}
interface F<I, O> {}
record A <A1, A2> (A1 a1, A2 a2)
implements
M<A1, A2>,
F<A1, A2>
{}
record N (Integer n1, Integer n2)
implements
M<Integer, Integer>,
F<Integer, Integer>
{}
interface C<C1, C2> extends M<C1, C2>, F<C1, C2> {}
record N2 (Integer n1, Integer n2) implements C<Integer, Integer> {}
private
static
<
D1,
D2,
D extends
M<D1, D2>
& F<D1, D2>
>
D
canItWork(final D1 d1, final D2 d2)
{
// return new A<>(d1, d2);
throw new UnsupportedOperationException();
}
private
static
<
D extends
M<Integer, Integer>
& F<Integer, Integer>
>
D
canItWorkAttempt2(final Integer d1, final Integer d2)
{
final C<Integer, Integer> blah = new N2(d1, d2);
return blah;
// return new N(d1, d2);
// throw new UnsupportedOperationException();
}
}