【问题标题】:Java interface generics, return type depending on argument genericJava接口泛型,返回类型取决于参数泛型
【发布时间】:2014-08-13 06:42:05
【问题描述】:

我有几个对象都实现了需要映射到的具体接口Op 任意类型。我正在尝试使用双重调度方法解决问题:

interface Mapper<R> {
    R process(Op1 op1);
    R process(Op2 op2);
}

interface Op<T>{
    <R> R process(Mapper<R> mapper);
}

class Op1 implements Op<String> {
    @Override
    public <R> R process(Mapper<R> mapper) {
        return mapper.process(this);
    }
}

class Op2 implements Op<String> {
    @Override
    public <R> R process(Mapper<R> mapper) {
        return mapper.process(this);
    }
}

我为指定的Ops创建了一个映射器,映射到String

Mapper<String> mapper = new Mapper<String>() {
    @Override
    public String process(Op1 op1) {
        return "1";
    }

    @Override
    public String process(Op2 op2) {
        return "2";
    }
};

问题

当我尝试将 Op 映射到 String 时:

Op op = new Op1();

String i = op.process(mapper);

进程的返回类型是Object而不是String。如果我更改 Op 接口,删除泛型,代码将按预期工作:

interface Op{
    <R> R process(Mapper<R> mapper);
}

为什么编译器不接受Op接口中的泛型定义?

【问题讨论】:

  • 您没有使用Op 上的泛型。您希望从他们那里获得什么?
  • 您说“编译器 [is] 不接受泛型定义”但没有包含错误消息。如果没有您看到的确切错误消息,很难确切知道您遇到了什么问题。
  • @Makoto 你是对的,我没有在示例中使用它,但即使在Op 方法上使用通用Top.process 类型的问题是相同的。如果我删除Top.process 返回正确的类型。
  • 顺便说一句,这是访问者模式,除了未使用的 T 类型参数之外,您的实现看起来大部分是正确的。
  • @LaurenceGonsalves 是的,错误是类型分配不兼容,op.process 返回 Object,而我希望它返回 String。

标签: java generics


【解决方案1】:

当您将Op1 分配给Op 类型的变量时,您使用的是原始类型。 Op 是泛型的,但您没有提供泛型类型参数,因此会发生类型擦除并且返回类型是 Object,而不是 String。您确实创建了一个Op1,它是一个Op&lt;String&gt;,但是当分配给一个原始Op 时,该信息会丢失。

当在方法而不是接口上声明泛型类型参数时,它会起作用,因为类型推断会接管并且R 被推断为String

要在使接口本身成为泛型时使其工作,只需在Op 变量上提供泛型类型参数。毕竟,Op1 就是Op&lt;String&gt;

Op<String> op = new Op1();

【讨论】:

  • 这个解决方案确实有效,但我必须知道Op1Op&lt;String&gt;。如果我这样做 Op&lt;?&gt; op = new Op1(); 它会按我的预期工作。但是为什么我必须这样做,而不仅仅是Op op = new Op1();
  • 当类型用作原始类型时,类/接口中的所有泛型都会进行类型擦除,甚至是不相关的类型参数。事实证明,Op&lt;?&gt; 也可以工作,因为调用的方法本身就是泛型的,从而使接口上定义的任何泛型都变得无用。删除Op 接口定义上的泛型类型参数似乎是一个更好的解决方案。
  • 我遇到的问题是op.process(mapper); 的返回类型,它应该取决于mapper 而不是Op。但是如果我确实使用Op&lt;?&gt; op = new Op1(); 它会按预期工作,我的问题主要是为什么会发生这种情况?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多