有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用扩展功能接口功能<?扩展父级,*>vs函数<?超级父级,*>vs函数<父级,*>

对于以下三种情况:

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
}

在第三种情况下,在父对象或子对象被传递给函数的情况下,两种情况下,我都会收到这样的编译时失败:

The method apply(capture#21-of ? extends Parent) in the type Function is not applicable for the arguments (Parent)

到目前为止,我的理解是:extends的意思是“是或扩展”,但上述情况导致我产生以下疑问:

  • 为什么Function<? extends T>不接受子对象、父对象
  • 其次是Function<? super T>同时接受子对象和父对象 由于父引用可以保存子对象(^{

编辑: 我理解集合(例如列表)中的PEC问题,比如声明的here,因为在那里List<? extends Parent>可能会得到一个List<GrandChild>的引用。现在,如果我们尝试在其中添加Child object,如果编译器之前没有捕捉到,它将导致运行时错误

Similarly is the Functional interface also behaving same & how are reference maintained here ?

该功能通过rgettman的示例进行了解释,但只是希望与集合相比有更清晰的画面

此外,这是可行的,但似乎PECS(Extends不能消耗任何东西)不应该被字面理解为:

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

共 (2) 个答案

  1. # 1 楼答案

    据编译器所知,check3的实际参数可能是Function<GrandChild, String>,对于需要GrandChild的方法来说,ParentChild都不是有效的类型

  2. # 2 楼答案

    • Why does Function is not accepting child, parent objects ?

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

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

    • Secondly is Function accepting both child, parent objects due to the fact that parent reference can hold child objects (Base obj=new Child()) ?

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