以下代码简化为问题的基本要点:
public class GenericTest
{
private interface CopyInterface<T extends CopyInterface<T>>
{
public void copyFrom(T source);
}
public void testMethod()
{
CopyInterface<?> target;
CopyInterface<?> source;
target.copyFrom(source);
}
}
这会导致以下编译器错误消息:
GenericTest.CopyInterface类型中的copyFrom(capture#1-of?)方法不适用于参数(GenericTest.CopyInterface)GenericTest.java / ACAF / src / de / tmasoft / acaftest / attributes第14行Java问题
当我使用原始类型作为变量目标时,我只得到一个原始类型警告。有没有办法在不使用原始类型的情况下编译?
答案 0 :(得分:4)
您必须使glm
通用并声明testMethod()
和source
属于同一类型:
target
答案 1 :(得分:2)
问题是您的源类型与目标类型的类型不兼容,但这是您的方法声明所需要的。
您的copyFrom
方法被声明为
public void copyFrom(T source);
这意味着target中对象的泛型类型参数必须与source的相同,即两者必须是某种类型T
。
当然,如果您使用类似?
的通配符类型,编译器无法判断?
在源和目标中是否具有相同类型T
,例如,它可能会有所不同。
CopyInterface<?> target = new Foo();
CopyInterface<?> source = new Bar();
以上?
代表两种不同的类型CopyInterface<Foo>
和CopyInterface<Bar>
。因此,正如您所看到的,当您使用?
时,您会丢失类型信息,以后编译器无法做出重要决策并且您会收到编译器错误。
回到copyFrom
方法,在这种情况下,编译器无法知道?
是否对应于方法T
所期望的类型copyFrom(T source)
,因此你的编译器错误。
如果源和目标属于同一类型,则不会出现此问题。
例如,如果您的接口实现如下:
class Foo implements CopyInterface<Foo> {
@Override public void copyFrom(Foo source){}
}
然后你不会有这样的问题:
Foo target = new Foo();
Foo source = new Foo();
target.copyFrom(source);
在这种情况下,T
在源和目标中都是Foo
,这与您的方法的签名兼容。
由于您看起来只是从源代码中读取,因此您还可以通过声明如下来放宽界面中的规则:
interface CopyInterface<T extends CopyInterface<T>> {
void copyFrom(CopyInterface<? extends T> source);
}
然后您的实现可能看起来像
class Foo implements CopyInterface<Foo> {
@Override public void copyFrom(CopyInterface<? extends Foo> source){}
}
然后你可以做
CopyInterface<Foo> target = new Foo();
CopyInterface<Foo> source = new Foo();
target.copyFrom(source);
但是只要你在这里使用通配符类型,我怀疑你是否可以设法让它工作。
答案 2 :(得分:1)
CopyInterface
参数的界限是无用的。 CopyInterface
并不关心可以复制的内容。 testMethod
关注copyFrom
的使用方式testMethod()
。所以你想让T
成为一个泛型方法,它对类型参数必须支持的内容施加限制。 (当然,在一个真实的例子中,testMethod
必须在private interface CopyInterface<T>
{
public void copyFrom(T source);
}
public <T extends CopyInterface<? super T>> void testMethod()
{
T target;
T source;
target.copyFrom(source);
}
的参数或返回类型中使用才能使其有意义。)
int value = array[1]*256 + array[0];
答案 3 :(得分:0)
对我来说很清楚,编译器无法检查源和目标是否属于同一类型。但我认为我可以通过显式转换而不是原始类型来解决它。所以我现在发现了以下解决方案,它似乎有效:
public class GenericTest
{
private interface CopyInterface<T extends CopyInterface<?>>
{
public void copyFrom(T source);
}
private class A implements CopyInterface<A>
{
@Override
public void copyFrom(A source)
{}
}
public static void copy(CopyInterface<?> source,
CopyInterface<? super CopyInterface<?>> target)
{
target.copyFrom(source);
}
@SuppressWarnings("unchecked")
public void testMethod()
{
CopyInterface<?> target = new A();
CopyInterface<?> source = new A();
((CopyInterface<? super CopyInterface<?>>) target).copyFrom(source);
copy(source, (CopyInterface<? super CopyInterface<?>>) target);
}
}
但我必须承认,我并不完全理解
之间的区别interface CopyInterface<T extends CopyInterface<?>>
和
interface CopyInterface<T extends CopyInterface<T>>