简体   繁体   中英

Why can't I cast the result of the super call directly?

So I have a interface that extends BiConsumer .

@FunctionalInterface
public interface MyActionWithParameters<E, P> extends BiConsumer<Selection<E>, P> {
    @Override
    default MyActionWithParameters<E, P> andThen(BiConsumer<? super Selection<E>, ? super P> after) {
        var newAction = BiConsumer.super.andThen(after);
        return newAction::accept;
    }
}

This works.

But if I try to return (MyActionWithParameters<>) BiConsumer.super.andThen(after); , I get a class cast exception.

Why is that? Why can I cast newAction::accept (ie a new BiConsumer ) but not the BiConsumer itself? I have a feeling the answer should be pretty obvious, but I just don't see it.

EDIT: full error

Caused by: java.lang.ClassCastException: class java.util.function.BiConsumer$$Lambda$2165/0x0000000840d10840 cannot be cast to class blah.blah.blah.MyFoo$MyActionWithParameters (java.util.function.BiConsumer$$Lambda$2165/0x0000000840d10840 is in module java.base of loader 'bootstrap'; blah.blah.blah.MyFoo$MyActionWithParameters is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @739fc679)

The reason why casting does not work is because whatever BiConsumer.andThen returns, it does not implement MyActionWithParameters . How on earth is BiConsumer , a JDK interface, supposed to know about your own custom interface? :-)

But using a method reference works, because by using a method reference, the type of object that super.andThen returns, aka newAction , no longer matters. What matters is the method - accept . Does accept have a compatible signature to satisfy the functional interface of MyActionWithParameters ? Yes it does, so it works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM