Вызов метода не соответствует сигнатуре метода, хотя метод использует более общие типы

Метод:

public static void incrementMapCounter( Map<Object,Number> tabulationMap, Object key ) {
  Number value = 0;
  if ( tabulationMap.containsKey(key) ) {
    value = tabulationMap.get(key);
  }
  value = value.doubleValue() + new Double(1);
  tabulationMap.put( key, value );
}

Вызов метода:

Map<String,Long> counts = new HashMap<>();
String key = "foo-bar";
incrementMapCounter( counts, key );

Ошибка (переформатированная):

The method
    incrementMapCounter(Map<Object,Number>, Object)
in ... is not applicable
    for the arguments  (Map<String,Long>, String)

Подпись метода является либо совпадающим, либо более общим:

  • Карта - это карта.
  • Строка - это объект (x2)
  • Длинный номер

Я немного запутался в этом.

Ответ 1

Это последние два. Строка и объект не совпадают. Дженерики не ковариантны, они инвариантны. Типы должны точно соответствовать. То же самое с длинным и числом.

Для вашей сигнатуры метода вы можете попробовать:

public static <T> void incrementMapCounter( Map<? extends T, ? extends Number> map, T key )
{ ...

Которое можно вызвать:

 HashMap<String, Integer> myMap = new HashMap<>();
 incrementMapCounter( myMap, "warble" );

Ответ 2

Обобщения инвариант, поэтому аргументы должны соответствовать аргументам, переданным так, чтобы значения могли быть добавлены в Collection

public static void incrementMapCounter(Map<String, Long> map, Object key) {