2015-10-21 2 views
0

После попытки идентифицировать проблему с моим универсального метода, я закончил с помощью следующего кода:Не удается вывести общий тип

 Map<String, BiConsumerThatThrows<CheckPayment, XMLEventReader>> a = CheckPayment.childMapper; 
     BiConsumerThatThrows<CheckPayment, XMLEventReader> a1 = a.get("1"); 
     BiConsumerThatThrows<? super CheckPayment, XMLEventReader> b1 = a1; 
     Map<String, BiConsumerThatThrows<? super CheckPayment, XMLEventReader>> b = new HashMap<>(); 
     b.put("1", b1); 
     b = a; 

Он не будет компилировать следующим ошибка (я отформатировал его, чтобы сделать его более удобным для чтения):

[ERROR] /D:/lalala/MyClass.java:[152,27] 
    incompatible types: 
     java.util.Map< 
      java.lang.String, 
      blablabla.BiConsumerThatThrows< 
       blablabla.CheckPayment, 
       javax.xml.stream.XMLEventReader 
      > 
     > 
    cannot be converted to 
     java.util.Map< 
      java.lang.String, 
      blablabla.BiConsumerThatThrows< 
       ? super blablabla.CheckPayment, 
       javax.xml.stream.XMLEventReader 
      > 
     > 

Что самое удивительное, он выходит из строя только на последней строке данного фрагмента кода.

Почему это происходит? Что можно сделать для выполнения такого задания?

Я использую Oracle JDK 1.8u40 x64.

P.S. Вот упрощенный пример:

Set<Set<String>> sets = new HashSet<>(); 
Set<Set<? super String>> sets2 = new HashSet<>(); 
sets2 = sets; 

Ошибка:

incompatible types: java.util.Set<java.util.Set<java.lang.String>> cannot be converted to java.util.Set<java.util.Set<? super java.lang.String>> 

P.P.S. Даже это не работает:

Set<Set<Object>> sets2 = new HashSet<Set<String>>(); 

Почему?

+0

Я хотел бы предложить, что вы рефакторинг кода и сгенерируйте проблема с менее сложными структурами и именами, так что было бы легче понять вашу проблему. –

+0

Вы указали функцию equals()? Я предлагаю вам прочитать следующее: http://stackoverflow.com/questions/1628718/java-type-safety-generics-equals – cristianhh

+0

Вы получаете типы несовместимых ошибок, потому что вы назначаете несовместимые типы ... – Ian

ответ

3

Проблема в том, что общие ограничения параметров типа не являются прозрачными для вложенных ограничений. A Map<String, List<Integer>> - это другой тип: Map<String, List<? super Integer>>, и вы не можете назначить его другому. Это проблема, с которой вы сталкиваетесь.

Чтобы исправить это, вам нужно сделать подстановочные применить весь путь к общей декларации на высшем уровне с extends:

Map<String, ? extends List<? super Integer>> m = new HashMap<String, List<Integer>>() 

Обратите внимание, что это extends, не super, поскольку List<Integer> является a под тип List<? super Integer> (я также нахожу этот mindbending). Так что в вашем случае это будет:

Map<String, ? extends BiConsumerThatThrows<? super CheckPayment, XMLEventReader>> b = ... 

и упрощенный пример:

Set<? extends Set<? super String>> sets2 = new HashSet<>(); 

Это может помочь с пониманием этого: http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ104

+0

Спасибо, похоже, что это так. Однако похоже, что это не проблема для функциональных интерфейсов: 'Функция > childMappers = (s) -> { if (CheckPayment.childMapper.containsKey (s)) return CheckPayment.childMapper.get (s); else if (AbstractOperation.childMapper.containsKey (s)) return AbstractOperation.childMapper.get (s); else return null; }; ' –