java - 为什么 Java 泛型类型推断会在链式方法调用中中断?

标签 java generics compilation type-inference

查看以下示例中泛型类型的类型推断,我说不出为什么 methodAutoTypeInference工作正常,但 methodNotCompilable (几乎相同)无法编译和管理它,编译器需要额外的技巧,例如 methodWorkaroundTypeHintmethodWorkaroundTypeCast .
methodNotCompilable有什么问题导致编译器不确定表达式类型和方法结果类型是否兼容?

Stream<CharSequence> methodAutoTypeInference() {
  return Stream.of("a");
}

Stream<CharSequence> methodNotCompilable() {
  return Stream.of("a").distinct(); 
  //    incompatible types:  java.util.stream.Stream<java.lang.String>
  // cannot be converted to  java.util.stream.Stream<java.lang.CharSequence>
}

Stream<CharSequence> methodWorkaroundTypeHint() {
  return Stream.<CharSequence>of("a").distinct();
}

Stream<CharSequence> methodWorkaroundTypeCast() {
  return Stream.of((CharSequence) "a").distinct();
}

最佳答案

This answer from JDK Developers themselves有点覆盖相同的区域。请注意 Stuart Marks 说:“编译器可能会得到增强,以在 future 版本中涵盖这种情况”。虽然这种情况在 lambdas 附近,这与您所拥有的没有太大不同。这只是编译器(目前)的工作方式。我们对此“卡住了”。
您可以在编译器如何思考 return Stream.of("a").distinct(); 的分辨率下进行查看。并决定使用什么类型,通过:

javac --debug=verboseResolution=all
在一个未记录的标志中。如果您使用该标志进行编译,您将看到一些大输出:
  with actuals: no arguments
  with type-args: no arguments
  candidates:
      #0 applicable method found: Object()
DeleteMe.java:60: Note: resolving method of in type Stream to candidate 1
        return Stream.of("a").distinct();
                     ^
  phase: BASIC
  with actuals: String
  with type-args: no arguments
  candidates:
      #0 not applicable method found: <T#1>of(T#1...)
        (cannot infer type-variable(s) T#1
          (argument mismatch; String cannot be converted to T#1[]))
      #1 applicable method found: <T#2>of(T#2)
        (partially instantiated to: (String)Stream<String>)
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in method <T#1>of(T#1...)
    T#2 extends Object declared in method <T#2>of(T#2)
DeleteMe.java:60: Note: Deferred instantiation of method <T>of(T)
        return Stream.of("a").distinct();
                        ^
  instantiated signature: (String)Stream<String>
  target-type: <none>
  where T is a type-variable:
    T extends Object declared in method <T>of(T)
DeleteMe.java:60: Note: resolving method distinct in type Stream to candidate 0
        return Stream.of("a").distinct();
                             ^
  phase: BASIC
  with actuals: no arguments
  with type-args: no arguments
  candidates:
      #0 applicable method found: distinct()
  where T is a type-variable:
    T extends Object declared in interface Stream
DeleteMe.java:60: error: incompatible types: Stream<String> cannot be converted to Stream<CharSequence>
        return Stream.of("a").distinct();
                                      ^
1 error
我想最重要的部分是:(partially instantiated to: (String)Stream<String>)可以看到是什么类型的分辨率T是,是做方法调用的基础;不是整个调用链。如果会的话,顺便说一句,这会使编译器的工作变得相当复杂。对于像这样的简单链,事情可能看起来微不足道,但是当有很多时,它会变得非常复杂和复杂。尤其是当您发现 non-denotable types 时,这将进一步复杂化。

关于java - 为什么 Java 泛型类型推断会在链式方法调用中中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66089702/

相关文章:

Java 有没有办法初始化类型安全的通用数组?

linux - 在内核 debians 中包含 objTools(linux-headers 和 linux-image)

c++ - (C++入门第5版)练习1.20中的一个问题

java - Android AlertDialog 在特定 Activity 中不显示按钮

java - 在 Java 中解析格式为 "January 10th, 2010"的日期? (带序号指示符,st|nd|rd|th)

java - 为部署到 heroku tomcat 的 Java Web WAR 找不到添加依赖项的类

c# - 序列化专业列表<>

java - 如何改进下面的方法逻辑?

java - 如何分发 java GUI 构建器项目

java - 当页面中存在两个框架时如何移动物理鼠标