java - 泛型 - 编译器不一致 [jdk 1.8.0_162]

标签 java generics java-8 compiler-errors

我遇到了泛型问题,这让我对编译器实际如何处理泛型类型感到困惑。请考虑以下事项:

// simple interface to make it a MCVE
static interface A<F, S> {
    public F getF();    
    public S getS();
}

static <V, S> Comparator<A<V, S>> wrap(Comparator<S> c) {
    return (L, R) -> c.compare(L.getS(), R.getS());
}

以下将无法编译,因为在调用 thenComparing 时,两种泛型类型都被简化为 Object:

Comparator<A<String, Integer>> c = wrap((L, R) -> Integer.compare(L, R))
    .thenComparing(wrap((L, R) -> Integer.compare(L, R)));

但是如果我像下面的例子那样分解它们,一切都会正确编译(并运行):

Comparator<A<String, Integer>> c = wrap((L, R) -> Integer.compare(L, R));
c = c.thenComparing(wrap((L, R) -> Integer.compare(L, R)));

所以问题是:这里发生了什么?我怀疑这是由于编译器的一些奇怪行为而不是预期的语言规范?还是我在这里遗漏了一些明显的东西?

最佳答案

第二次尝试编译正确,因为你自己指定了一个变量的类型,告诉编译器它是什么,因为编译器没有足够的信息来弄清楚它。

看看这个简化的例子,它来自 vavr (顺便说一下)。有一个 Try<T>表示某些操作结果的类。通用参数T是该结果的类型。有一个静态工厂可以立即创建失败,这意味着我们这里没有结果,但是泛型参数仍然存在:

static <T> Try<T> failure(Throwable exception) {
    return new Try.Failure(exception);
}

T 在哪里?从这里来?用法如下所示:

public Try<WeakHashMap> method() {
  return Try.failure(new IllegalArgumentException("Some message"));
}

Try<WeakHashMap>这是我的选择,而不是编译器,您实际上可以在其中放入任何您想要的东西,因为您正在选择类型。

在你的例子中也是一样,Comparator具有通用参数 String只是,因为你指定了它并且编译器同意它(就像 Try<WeakHashMap> )。当你添加一个链式调用时,你迫使编译器自己推断类型,它是 Object ,因为它可能是另一种类型吗?

您还可以做什么(注意 Testing.<String, Integer>wrap ):

public class Testing {
  static interface A<F, S> {
    public F getF();
    public S getS();
  }

  static <V, S> Comparator<A<V, S>> wrap(Comparator<S> c) {
    return (L, R) -> c.compare(L.getS(), R.getS());
  }

  public static void main(String[] args) {
    Comparator<A<String, Integer>> comp = Testing.<String, Integer>wrap((L, R) -> Integer.compare(L, R))
      .thenComparing(wrap((L, R) -> Integer.compare(L, R)));
  }
}

关于java - 泛型 - 编译器不一致 [jdk 1.8.0_162],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54158402/

相关文章:

java - 检查日期是否早于 10 年和新于 20 年

java - 在同一个 Activity/布局中多次使用同一个 fragment

javascript - 如何在 Sonarqube Javascript Extension 中获取项目路径

java - JFrame 在关闭 Java 时退出

c# - 如何使用反射获得泛型类型的正确文本定义?

java - 使用 HashMap 时 Java 11 中的 ClassCastException 而不是 Java 8 中的?

java - 是否可以将路径变量和请求参数绑定(bind)到一个对象中?

java - 与java协调变化

java - 自动顺序显示图像

c# - 如何将 DataView、DataRowView 转换为通用类型列表