3

我无法为方法的输出声明一个完全通用的类型。情况如下:

class A<S,T>{
public Callback<B<S,T>,C<S,T>> method();
}

在我的代码中,我有其中之一;

A<String, ?> instance;

但是,当我打电话时

result = instance.method()

让编译器满意的唯一方法是声明

Callback<?, ?> result = instance.method()

但我真的很想更具体地说明我的泛型并声明

Callback<B<String, ?>,C<String, ?>> result = instance.method()

但是,由于每个通配符都是独立的,编译器会抱怨这是不正确的,说明它无法从

Callback<B<String,capture#3-of ?>,C<String,capture#3-of ?>>

有什么方法可以正确声明这种情况吗?

仅供参考,A、B 和 C 类来自外部库。我试图将我的实例声明为

A<String, Object>

但这也是我无法控制的第四类方法的结果:

class D<T>{
public A<T, ?> getObject();
}

D<String> start = new D<String>();
A<String, ?> = start.getObject();
...
4

2 回答 2

1

你可以有

Callback<? extends B<String, ?>, ? extends C<String, ?>> result
    = instance.method();
于 2013-03-01T04:17:42.907 回答
1

这确实是一个尴尬的情况,这是由于通配符捕获的限制以及 from 的返回类型不太理想D.getObject

有一些解决方法,但没有一个是漂亮的。第一种是简单地进行未经检查的演员表:

@SuppressWarnings("unchecked") //it's okay for the two captures not to match
Callback<B<String, ?>, C<String, ?>> result =
        (Callback<B<String, ?>, C<String, ?>>)instance.method();

编辑:一些编译器(更正确地)需要通过以下方式进行双重转换Callback<?, ?>

@SuppressWarnings("unchecked") //it's okay for the two captures not to match
Callback<B<String, ?>, C<String, ?>> result =
        (Callback<B<String, ?>, C<String, ?>>)(Callback<?, ?>)instance.method();

您还可以使用辅助方法 - 这是通配符捕获问题的常见解决方案:

static <T> void helper(A<String, T> a) {

    Callback<B<String, T>, C<String, T>> result = a.method();

    //logic
}

...

helper(instance);

更新:

实际上,您可以将这两种方法结合起来,至少将丑陋隔离到一个辅助方法中:

static <S, T> Callback<B<S, ?>, C<S, ?>> disentangleCallback(
        Callback<B<S, T>, C<S, T>> callback
) {
    @SuppressWarnings("unchecked") //it's okay for the two captures not to match
    final Callback<B<S, ?>, C<S, ?>> withWidenedTypes =
            (Callback<B<S, ?>, C<S, ?>>)(Callback<?, ?>)callback;
    return withWidenedTypes;
}

然后像这样使用它:

Callback<B<String, ?>, C<String, ?>> result =
        disentangleCallback(instance.method());

或者一个类似的方法,它简单地接受一个并通过调用自身A<S, T>返回一个,然后强制转换。Callback<B<S, ?>, C<S, ?>>method


另一个想法:如果第二个类型参数 ofA总是未知的,那么删除它并扩大返回类型可能会更容易method

class A<S> {
    public Callback<B<S, ?>, C<S, ?>> method() { ... }
}

T我意识到这将是一个不幸的让步,但如果它从来没有真正有用是有道理的。

于 2013-03-01T04:17:46.337 回答