为什么Java泛型类型推断在链式方法调用中中断? [英] Why does Java generics type inference break in chained method calls?

查看:0
本文介绍了为什么Java泛型类型推断在链式方法调用中中断?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

查看以下示例中泛型类型的类型推断,我说不出为什么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说:该编译器可能会在未来的发行版中得到增强以涵盖这种情况。尽管有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泛型类型推断在链式方法调用中中断?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆