代码之家  ›  专栏  ›  技术社区  ›  sksamuel

具有通配符不编译的Java泛型

  •  0
  • sksamuel  · 技术社区  · 14 年前

    我很难理解使用通配符的Java泛型的细点。具体来说,为什么不编译这个呢?

    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);
            }
        }
    }
    
    3 回复  |  直到 9 年前
        1
  •  1
  •   Thomas    11 年前

    编译器不知道您是否在列表和函数中使用相同的类型。所以你必须告诉他这个。

    试试这个:

    public <C extends PropertyType>void functionLoop(
                             List<C> list, Function<C, String> t) {
      for (C p : list) {
        t.call(p);
      }
    }
    
        2
  •  3
  •   Flavio    14 年前

    最正式的正确方法是

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

    我发现的泛型的最好解释是Joshua Bloch的“有效Java”。你可以找到一个小的摘录,它可以与你的例子相关。 presentation .

        3
  •  0
  •   Vladimir Ivanov    14 年前

    因为 call(Apartment a) 应该得到 Apartment 对象作为参数传递 PropertyType 对象。虽然 公寓 IS-A 属性类型 但是 属性类型 IS-NOT-A Appartment .