27

このコードはJava 8ではコンパイルできますが、Java 7ではコンパイルできません。

class Map<K,V> {
    static <K,V> Map<K,V> empty() {return null;}
    Map<K,V> put(K k, V v) {return null;}
    V get(K k) {return null;}
}

class A {
    static void f(Map<Integer,String> m){}
    public static void main(String[] args) {
        f(Map.empty());
    }
}

それはの具体的なタイプを推論しないMapから返されているMap.empty()

$ javac7 A.java
A.java:10: error: method f in class A cannot be applied to given types;
        f(Map.empty());
        ^
  required: Map<Integer,String>
  found: Map<Object,Object>
  reason: actual argument Map<Object,Object> cannot be converted to Map<Integer,String> by method invocation conversion
1 error

変更するとコンパイルされます。fへ電話するf(Map.<Integer,String>empty());。 Java 8では、これに頼ることなく動作します。

しかしあなたが変えるならfへ電話するf(Map.empty().put(1,"A").put(2,"B"));、それはJava 7と8の両方で、もう一度コンパイルに失敗します。なぜですか?

$ $javac7 A.java 
A.java:10: error: method f in class A cannot be applied to given types;
        f(Map.empty().put(1,"A").put(2,"B"));
        ^
  required: Map<Integer,String>
  found: Map<Object,Object>
  reason: actual argument Map<Object,Object> cannot be converted to Map<Integer,String> by method invocation conversion
1 error

$ $javac8 A.java
A.java:10: error: incompatible types: Map<Object,Object> cannot be converted to Map<Integer,String>
        f(Map.empty().put(1,"A").put(2,"B"));
                                    ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

$ $javac8 -Xdiags:verbose A.java
A.java:10: error: method f in class A cannot be applied to given types;
        f(Map.empty().put(1,"A").put(2,"B"));
        ^
  required: Map<Integer,String>
  found: Map<Object,Object>
  reason: argument mismatch; Map<Object,Object> cannot be converted to Map<Integer,String>
1 error


  • それを作るだけstatic Map empty() {return null;}とにかく、ジェネリックを使用して修飾子を追加するのは好きではありません。 - ug_

1 답변


31

どうして ?

総称型の型推論は連鎖呼び出しに拡張されていないためです。

から総称型推論に関するJavaチュートリアル

ターゲット型とは何かという概念が、メソッド引数を含むように拡張されました。

だからこそ、このコード:

f(Map.empty());

コンパイルします。

しかし、このコードは、これが連鎖呼び出しであるためではありません。

f(Map.empty().put(1,"A").put(2,"B"));

また、小さな段落を見つけることができますJSR-000335評価用JavaTMプログラミング言語最終リリースのラムダ式(特にパートD):

a()。b()で、bの呼び出しからaの呼び出しに型情報を渡すことで、推論を「連鎖」させることにある程度の関心が寄せられています。部分的な情報は両方向に通過しなければならないので、これは推論アルゴリズムの複雑さに別の次元を加える。 a()の戻り型の消去がすべてのインスタンス化に対して固定されている場合にのみ機能します(例:List)。ターゲットタイプは簡単に導き出すことができないため、この機能はpoly表現モデルにはあまり適合しません。しかし、おそらく追加の機能拡張により、将来追加される可能性があります。

Java 9でもそうでしょう。

リンクされた質問


関連する質問

最近の質問