-1
public class Test<T extends Test.Mapper<?>> {
    SomeFactory<T> factory;

    public Test(SomeFactory<T> factory) {
        this.factory = factory;
    }

    public <V> V handle(T<V> request) { // fails how to get Class<V> of request.getCls() of a mapper or its subtype?
        HttpUriRequest httpUriRequest = factory.get(request); // does not work
        // decode response and return it as an object represented by request.getCls
        return null;
    }

    public interface Mapper<T> {
        Class<T> getCls();
    }

    public interface SomeMapper<T> extends Mapper<T> {
        void doSomeAdditional();
    }

    public interface SomeFactory<T extends Test.Mapper<?>> {
        HttpUriRequest get(T mapper);
    }
}

handle 方法是一种通用方法,它执行 http 请求,然后将响应主体解码为由 Mapper 的 getCls() 方法表示的对象。我希望这个类能够处理 Mapper 的不同子类型,因为 SomeFactory 实现需要访问一些仅特定于该类型的方法

与此类似的东西

SomeFactory<SomeMapper<?>> somefactory = // factory implementation
Test<SomeMapper<?>> test = new Test<SomeMapper<?>>(someFactory);
test.handle(implementation of SomeMapper<Integer>); // should return an instance of Integer

澄清:基本上Test的实例化应该只对应于Test的实际类型(SomeMapper或Mapper)的handle()类型。然后,handle 方法可以接受这种实际类型的任何请求。

IE 如果是Test<SomeMapper<?>> test ,我有类似的请求

ASomeMapper implements SomeMapper<Double> {}
BSomeMapper implements SomeMapper<Integer> {}

test.handle(new ASomeMapper()); // this should return Double
test.handle(new BSomeMapper()); // this shold return Integer

也许我应该重新设计?

4

1 回答 1

1

我不确定这对于你想要做的事情是否可以接受,但你可以这样做:

public class Test<V, T extends Test.Mapper<V>> {
    SomeFactory<T> factory;

    public Test(SomeFactory<T> factory) {
        this.factory = factory;
    }

    public V handle(T request) {
        return null;
    }

    public static interface Mapper<A> {
        Class<A> getCls();
    }

    public interface SomeMapper<T> extends Mapper<T> {
        void doSomeAdditional();
    }

    public interface SomeFactory<T extends Test.Mapper<?>> {
        HttpUriRequest get(T mapper);
    }
}

或者您可以这样做,但在调用具有超过 2 个参数的泛型方法时,您必须始终定义参数:

    public <V, Z extends T> V handle(Z request) {
        return null;
    }

您无法像在示例中尝试做的那样进一步参数化参数。

另一种解决方案是返回一步并执行此操作:

    public <V> V handle(Test.Mapper<V> request) {
        return null;
    }

所以你保证它是一个合适的 Mapper 类型,但不保证它的实现。

至于你如何尝试使用它,它根本不会那样工作。您要定义的是通用方法(不仅是类)。所以基本上必须为该方法提供另一个参数,该参数由赋值定义。

无论您如何实现此 ASomeMapper,您的行都不会编译:

test.handle(new ASomeMapper());

它会要求您执行以下操作:

Double value = test.handle(new ASomeMapper());

只有这样,它才知道您实际上想要返回 Double。如果 ASomeMapper 与 Double 参数不匹配,编译器会报错,但如果匹配,它将编译。或者,如果您这样定义它:

Object value = test.handle(new ASomeMapper());

您仍会看到一条警告,在您的情况下应将其视为错误。因为它并不真正知道您要返回什么,并且会返回 ASomeMapper 中编码的任何内容,而无需进行任何类型检查。如果您想将它分配给一个 Object 并且仍然需要进行类型检查,那么您必须显式地参数化方法调用。

new Test<SomeMapper<?>>(null).<Double>handle(null);
于 2013-02-25T21:55:33.343 回答