Reputation: 21586
Java8 lets me use a method declaration as implementation of any of my interfaces, as long as it only contains one method.
However once it is defined, the type cannot be changed.
My code:
import java.util.function.IntConsumer;
public class A {
interface MyConsumer {
void doSomething(int i);
}
public static void main(String[] args) {
IntConsumer i = A::consume;
MyConsumer i2 = A::consume;
IntConsumer i3 = (IntConsumer) i2; // ClassCastException
MyConsumer i4 = (MyConsumer) i; // ClassCastException
IntConsumer i5 = i2; // does not compile
MyConsumer i6 = i; // does not compile
IntConsumer i7 = i2::doSomething; // workaround, as suggested by @Eran http://stackoverflow.com/a/35846001/476791
MyConsumer i8 = i::accept;
Object i9 = A::consume; // does not compile
Object i10 = (IntConsumer) A::consume; // works
Object i11 = (MyConsumer) A::consume; // works
Object i12 = (MyConsumer) (IntConsumer) A::consume; // does not work
}
static void consume(int i) {
System.out.println(i);
}
}
Note: if you inline some of the variables, then some of the non-working examples suddenly start to work.
My thoughts in detail:
IntConsumer i = A::consume
is valid, then A::consume
has to implement IntConsumer
MyConsumer i2 = A::consume
is valid, then A::consume
has to implement MyConsumer
A::consume
implements both, IntConsumer
and MyConsumer
, then casting should be possibleIs there another way to "cast" or "change" the type of the consumer afterwards?
Upvotes: 3
Views: 114
Reputation: 198163
A::consume
has no inherent type. When it appears in a context in which it is being used or assigned to a functional interface type, the compiler will create an object of that type implemented using A::consume
.
Once you have that, you have an object of that specific functional interface type. It's not a method; it's a perfectly normal object. Java objects can't pretend to be other types their real type doesn't implement or extend.
So once you have an IntConsumer
, you can't cast it to a MyConsumer
. You can use it to get a method reference that can then become a new MyConsumer
, but that one object will always be just an IntConsumer
, nothing more.
Upvotes: 1
Reputation: 533570
Is there another way to "cast" or "change" the type of the consumer afterwards?
You can't change the actual type of an object(1). You can cast a primitive, and you can cast a reference to another type suitable for the object referenced.
What you can do is wrap the instance with the type you want.
MyConsumer mc = ((IntConsumer) A::consume)::accept;
(1) you can hack the class pointer in the object header, but this is highly unlikely to be a good idea.
Upvotes: 3