2010-11-16 3 views
0

У меня возникли проблемы с пониманием тонкостей Java-дженериков с подстановочными знаками. в частности, почему это не компилируется.Java Generics с подстановочными знаками не компилируется

public class Test { 

    abstract class Function<A, B> { 
     abstract B call(A a); 
    } 

    interface PropertyType { 
     String bubbles(); 
    } 

    class Apartment implements PropertyType { 
     @Override 
     public String bubbles() { 
      return "bubbles"; 
     } 
    } 

    public void invokeFunctionOnAList() { 
     List<Apartment> apts = new ArrayList<Apartment>(); 
     functionLoop(apts, new Function<Apartment, String>() { 

      @Override 
      String call(Apartment a) { 
       return a.bubbles(); 
      } 
     }); 
    } 

    public void functionLoop(List<? extends PropertyType> list, Function<? extends PropertyType, String> t) { 
     for (PropertyType p : list) { 
      t.call(p); 
     } 
    } 
} 
+0

Я вижу проблему, и большинство компиляторов Java будут довольно откровенно об этом. Какие ошибки вы получаете? – PaulJWilliams

+3

Если вы собираетесь сообщить, что что-то не удается скомпилировать, вы должны * всегда * включать сообщение об ошибке и местоположение. –

ответ

1

Ваш компилятор не знает, используете ли вы один и тот же тип в списке и функции. Поэтому вы должны сказать ему это.

Попробуйте это:

public <C extends PropertyType>void functionLoop(
         List<C> list, Function<C, String> t) { 
    for (C p : list) { 
    t.call(p); 
    } 
} 
+0

О, я вижу, потому что подтип списка не обязательно должен быть подтипом функции? – monkjack

+0

Да, тип объектов в вашем списке должен иметь тот же тип вашего параметра в вашем методе вызовов в функции. –

0

потому что call(Apartment a) должен получить Apartment объект в качестве параметра, и вы передаете PropertyType объект. То есть Apartment is-a PropertyType, но PropertyType is-NOT-a Appartment.

3

Наиболее формально правильный способ поставить этот код на самом деле

public <C extends PropertyType> void functionLoop(
     List<C> list, Function<? super C, String> t) { 
    for (C p : list) { 
     t.call(p); 
    } 
} 

Лучшее объяснение дженериков я нашел на «Эффективное Java» Джошуа Блоха. Вы можете найти небольшую выдержку, которая может относиться к вашему примеру в этом presentation.

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