2013-05-28 4 views
1
public class ExplicitTypeSpecification { 

    static void f(Map<Integer, String> map){} 

    public static void main(String[] args){ 
     New c = new New(); 
     f(c.map()); 
    } 
} 

class New <K, V>{ 
    Map<K, V> map(){ 
     return new HashMap<K, V>(); 
    } 
} 

Этот код компилируется без ошибок.Параметрированный класс с параметризованным методом

Затем мы делаем некоторые изменения в классе новых:

class New { 
    <K, V>Map<K, V> map(){ 
     return new HashMap<K, V>(); 
    } 
} 

Мы параметрироваться только метод map(), но не весь класс. Но в этом случае ошибка компиляции в встречается, линии f(c.map());:

java: f(java.util.Map<java.lang.Integer,java.lang.String>) in 
Generics.ExplicitTypeSpecification.ExplicitTypeSpecification cannot be applied to 
(java.util.Map<java.lang.Object,java.lang.Object>)* 

Мы можем указать явные типы f(c.<Integer, String>map()); но я заинтересован в Почему мы получим ошибку компиляции?.

В обоих случаях метод map() возвращает Map<Object, Object> объект, но в первом случае мы получаем только предупреждение о непроверенной задаче.

Вопрос: почему во втором случае у нас более строгий контроль типа?

Что такое dirrefence между new HashMap() и новыми HashMap<Object, Object>()? Ответ на эту проблему решает.

+0

Интересный вывод, тем более, что 'Map map = c.map(); f (map); 'компилируется. Я думаю, что это имеет какое-то отношение к способности компилятора угадать правильные значения для 'K' и' V'. – Cephalopod

ответ

2

В первом случае вы используете необработанный тип New (а не New<Integer, String>), поэтому вся общая проверка типов отключена. Это работает как режим совместимости для старого (Java 1.4) кода.

+0

Но во втором случае я также использую raw type 'New'. Я только что изменил параметризацию класса и метода. Мой вопрос в том, почему в этом случае включена универсальная проверка типов? – AJlxuMuk

+0

Во втором случае 'New' не является общим, поэтому это всего лишь один тип, нет сырого типа и т. Д. Таким образом, компилятор не отключает проверку общего типа. Вместо этого он пытается вывести общий тип для возвращаемого типа 'c.map()' автоматически и терпит неудачу. Используйте 'Map map = c.map();', чтобы увидеть работу автоматического вывода. –

0

Если вы не укажете параметры типа, обратная совместимость с Java 1.4 предположит, что вы хотите «Объект». Кроме того, вы получите предупреждение об этом.

Так что ваша функция эквивалентна:

public static void main(String[] args){ 
    New c = new New(); 
    f(c.<Object, Object>map()); 
} 

И тогда вы получите ошибку о том, что вы пытаетесь использовать значение Map<Object, Object>, где параметр Map<Integer, String> ожидается.

Примечание: Map<Integer, String> является не a подтип Map<Object, Object>.

+0

Вы правы. ** Но ** если вы используете ** параметризованный класс ** (не параметризованный метод) - код вверху, вы ** не получаете ошибку **. Обратите внимание: в этом случае метод map() также возвращает «Map », потому что объект New является raw, а метод f() получает этот объект в качестве параметра, когда ему действительно нужна «Map '. – AJlxuMuk