Вывод общего типа не работает с цепочкой метода?
Этот код компилируется в 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
1 ответ
Зачем?
Поскольку вывод типов обобщенных типов не был расширен до цепного вызова.
Из учебника Java по выводу обобщенных типов:
Понятие того, что является целевым типом, было расширено, чтобы включить аргументы метода.
Вот почему этот код:
f(Map.empty());
компилирует.
Но этот код не потому, что это цепной вызов:
f(Map.empty().put(1,"A").put(2,"B"));
Вы также можете найти небольшой абзац в лямбда-выражениях JSR-000335 для финального выпуска языка программирования JavaTM для оценки (в частности, части D):
Был некоторый интерес к разрешению вывода для "цепочки": в a(). B (), передача информации о типе от вызова b к вызову a. Это добавляет еще одно измерение к сложности алгоритма вывода, так как частичная информация должна проходить в обоих направлениях; это работает только тогда, когда стирание возвращаемого типа a () фиксировано для всех экземпляров (например, List). Эта функция не очень хорошо вписывается в модель выражения поли, поскольку целевой тип не может быть легко получен; но, возможно, с дополнительными улучшениями он может быть добавлен в будущем.
Так что, возможно, в Java 9.
Какой тип Map.Entry.comparingByValue(). Reversed ()?- Просто ответить на этот вопрос проще.
unSortedMap.entrySet().stream()
.filter(e -> e.getValue() > 1)
.sorted(Entry.comparingByValue(Comparator.reverseOrder()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));