パラメータの型が指定されていない限り、Javaは、一般的なラムダ引数をコンパイルすることはできません

user2770791:

テスト中、私は(このように新しいバージョンと私のいるassertTrue()メソッドの一部を置き換える)5.0に私のJUnitのアップグレード。そうした後、私は私のテストのいずれかがコンパイルできませんでした。私は、JUnitのか、他の依存関係がないと、昔ながらのJavaへの問題を下に減少しました。結果はコンパイルされません、次のコードです。

  public static void recreate() {
    // This does NOT work
    Recreation.assertTrue(identity((x) -> Boolean.TRUE)); 
    // This DOES work
    Recreation.assertTrue(identity((String x) -> Boolean.TRUE)); 
  }

  private static class Recreation {
    public static void assertTrue(boolean b) {
      System.out.println("boolean argument: " + b);
    }

    // If this method is removed, the code will compile. 
    public static void assertTrue(Supplier<Boolean> booleanSupplier) {
      System.out.println("supplier argument: " + booleanSupplier.toString());
    }
  }

  private static <K> K identity(Function<String, K> function) {
    return function.apply("hello");
  }

上記の例に示すように、次のいずれかに該当する場合、コードはコンパイルされます。

  1. ラムダパラメータの型が指定されています

  2. オーバーロードいるassertTrue(サプライヤーbooleanSupplier)メソッドが除去されます

これは、型推論/消去の問題、または何ここで起こっされることがありますか?

ビルドエラー:

Error:(10, 35) incompatible types: inference variable K has incompatible bounds
    lower bounds: java.util.function.Supplier<java.lang.Boolean>,java.lang.Object
    lower bounds: java.lang.Boolean

仕様:

openjdk version "11.0.1" 2018-10-16
OpenJDK Runtime Environment (build 11.0.1+13-Ubuntu-3ubuntu114.04ppa1)
OpenJDK 64-Bit Server VM (build 11.0.1+13-Ubuntu-3ubuntu114.04ppa1, mixed mode, sharing)

OS: Ubuntu 14.04.5 LTS

EDIT:問題は、同様のJava 8上に存在確認:

java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)
exit status 1
Main.java:10: error: incompatible types: inferred type does not conform to upper bound(s)
    Recreation.assertTrue(identity((x) -> Boolean.TRUE));
                                  ^
    inferred: Boolean
    upper bound(s): Supplier<Boolean>,Object
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
Bustanulアリフィン:

周りを見て、ここでは、Java言語仕様を読んだ後https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.1

私は2つのステップがここにあると思います。

まず、過負荷に解像度がのタイプ推測できなかったidentity((x) -> Boolean.TRUE)、それは暗黙のラムダだからと、私はそれは単純化のために考慮されていないと思います。したがって、パラメータの検索と利用を広げますpublic static void assertTrue(Supplier<Boolean> booleanSupplier)

第二には、解像度をオーバーロードした後、行われる型推論でキックを。今回はそれが本当にある推論された型をチェックBooleanし、それはとの互換性がありませんので、Supplier<Boolean> booleanSupplierあなたがコンパイル・エラーが発生します。

前の回答と同様に、この解決策はありますが、

たとえば、

Recreation.assertTrue(identity((x) -> () -> Boolean.TRUE));

私はここで良い説明を見つけた:Java8:ラムダとオーバーロードされたメソッドを持つ曖昧

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=168246&siteId=1