使用具有功能接口的扩展-Function <!-?扩展Parent,*-> vs Function <!-?超级父项,*-> vs Function <父项,* =“”>

时间:2018-11-29 17:31:57

标签: java generics inheritance casting functional-programming

对于以下三种情况:

void check1(Function<Parent, String> function) {
    Parent p = new Parent(); 
    function.apply(p); // compiles fine
    Child c = new Child();
    function.apply(c); // compiles fine
}

void check2(Function<? super Parent, String> function) {
    Parent p = new Parent();
    function.apply(p); // compiles fine
    Child c = new Child();
    function.apply(c); // compiles fine
}

void check3(Function<? extends Parent, String> function) {
    Parent p = new Parent();
    function.apply(p); // compile time error
    Child c = new Child();
    function.apply(c); // compile time error
}

在第3种情况下,对于两者情况,如将Parent对象或Child对象传递给函数的情况,我都会收到这样的编译时失败:

  

类型中的方法apply(capture#21-of?扩展Parent)   功能不适用   为参数(父母)

到目前为止,我的理解是:extends的确表示“是或扩展”,但以上情况使我提出以下查询:

  • 为什么Function<? extends T>不接受子对象,父对象?
  • 第二个是Function<? super T>接受子对象和父对象 由于父引用可以保存子对象Base obj=new Child())吗?

编辑: 我了解here之类的集合(例如列表)中的PECS问题,因为在那里List<? extends Parent>可能会得到List<GrandChild>引用。现在,如果我们尝试在其中添加Child object,那么如果编译器较早发现它,则会导致运行时错误

  

类似地,Functional界面也具有相同的功能以及如何   此处保留了参考?

rgettman举例说明了该功能,但与集合相比,它只需要更清晰的图片。

此外,这种方法还可以,但是很好,但似乎 PECS(扩展不能消耗任何东西)

<T extends Parent> void check4(List<T> myList, Function<T, String> func) {
func.apply(myList.get(0)); // compiles successfully 
}

2 个答案:

答案 0 :(得分:1)

  
      
  • 为什么Function不接受子对象,父对象?
  •   

您的参数function可以是根据Parent上限采用Parent? extends子类型的任何方法。这意味着check3可以接受Function<Child, String>,而您不能传递Parent。这就是apply方法上出现编译器错误的原因;当函数参数的类型未知时,编译器不能保证类型安全。

还可能存在Parent任何个未知子类,例如SiblingGrandchild,它们也扩展了Parent。这意味着Child也不能是apply的参数。 function可以是Function<Grandchild, String>

  
      
  • 由于父引用可以容纳子对象(Base obj = new Child()),因此第二个函数同时接受子对象和子对象吗?
  •   

之所以有效,是因为? super Parent是一个下限。这意味着function作为参数可以是Function<Parent, String>Function<Object, String>。因为该函数可能需要一个Parent甚至是一个Object,所以始终可以将Parent传递给该函数并调用apply,因此编译在此处成功。

答案 1 :(得分:0)

check3 可能的实际参数例如就编译器所知,Function<GrandChild, String>并不适用于需要Parent的方法,ChildGrandChild都不是有效类型。