2015-03-06 2 views
4

Я столкнулся с поведением java-компилятора (jdk1.6.0_45), которое я не могу объяснить. Вот два фрагмента кода - первый компилируется, а второй - нет. компилирует:Javac не может вывести тип без вспомогательной переменной

Map<String, Collection<MyClass>> result = Maps.newHashMap(); 

Comparator<? super MyClass> comparator = comparatorProvider.getComparator(*some parameter*); 
TreeMultiset<MyClass> multiSet = TreeMultiset.create(comparator); 
result.put("blahBlah", multiSet); 

не компилируется:

Map<String, Collection<MyClass>> result = Maps.newHashMap(); 

Comparator<? super MyClass> comparator = comparatorProvider.getComparator(*some parameter*); 
result.put("blahBlah", TreeMultiset.create(comparator)); 

Карта и TreeMultiset классов являются частью библиотек Google-гуава.

Второй фрагмент не компилируется, дает следующее сообщение об ошибке:

put(java.lang.String,java.util.Collection<MyClass>) in java.util.Map<java.lang.String,java.util.Collection<MyClass>> cannot be applied to (java.lang.String,com.google.common.collect.TreeMultiset<java.lang.Object>) 

Обратите внимание, что java.lang.Object часть ошибки. Таким образом, кажется, что javac не смог вывести тип TreeMultiset без явной переменной «multiset».

Вот код метода фабрики:

@SuppressWarnings("unchecked") 
public static <E> TreeMultiset<E> create(
    @Nullable Comparator<? super E> comparator) { 
return (comparator == null) 
     ? new TreeMultiset<E>((Comparator) Ordering.natural()) 
     : new TreeMultiset<E>(comparator); 
} 

Любая ясность на такое поведение было бы очень ценна.

Даже IDE (Intellij IDEA) не дает ошибок.

+2

Вызовите свои предупреждения. У вас много непроверенных операций, которые могут вызвать некоторые неожиданные результаты. – Necreaux

+0

Нет ни одной непроверенной операции - метод getComparator() параметризуется входным параметром и безопасным типом. И метод Factory, предоставленный для TreeMultiset, является частью библиотеки Google-Guava, и я ничего не могу сделать. –

+0

С меткой это с Гуава. Кто-то, кто больше знаком с Гуавой, может помочь лучше. – Necreaux

ответ

3

Выводы типа Java не так сильны, как хотелось бы (по сравнению, скажем, с Scala). Вы можете дать аргумент того же типа без вспомогательной переменной:

result.put("blahBlah", TreeMultiset.<MyClass>create(comparator)); 
+0

Да, я знаю, что могу, но я все еще не могу понять, в чем проблема в этом конкретном случае. В фабричном методе четко указано: «возьмите ограниченный тип переданного компаратора и верните TreeMultiset (который реализует интерфейс Collection) этого типа». В этом случае он должен всегда возвращать TreeMultiset . Почему я вынужден объявить тип явно? –

+1

В первом примере результат вызова «create» присваивается переменной TreeMultiset . Поэтому компилятор сообщает, что единственным возможным аргументом типа является MyClass --- это довольно простой вывод. Во втором примере результат вызова «create» передается как аргумент «put», который сам по себе является общим методом. Мы с вами можем видеть, что аргумент типа для put будет Collection , поэтому единственный способ, которым это будет работать, - это аргумент типа для create - это MyClass, но это дополнительный шаг логики, который компилятор Java не реализует. –

Смежные вопросы