Note: I have found questions regarding the type casting with the IBinder and Binder but they focus on fixing issues. My issue is understanding why the cast is not illegal in the first place. I have also tried the same operation in BlueJ with replacement classes but using the same structure and it fails at runtime.
Here is the code which contains the cast that I thought should be illegal.
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalService.LocalBinder binder = (LocalService.LocalBinder) service; //<------------ this cast right here. Note that LocalBinder extends Binder which implements the IBinder interface
mService = binder.getService();
mBound = true;
}
I thought assigning the IBinder (the service variable) parent class variable to a typed variable of a subclass of the IBinder (i.e. the LocalService.LocalBinder 'binder' variabke) and then down casting IBinder to its subclass was illegal.
In other words I thought, in general syntax that this was illegal: Child = (Child) variableOfTypeParent; //This passes the compiler but gets a class cast exception at run-time.
Though I do understand this to be legal: Child = (Child) variableOfTypeParentAssigned2Child; //But this isn't the case here.
Hopefully the superior minds on here can throw me a bone or show me where I can read up on this kind of casting.
Edit: Here is my code from BlueJ:
interface IBinder {
}
class Binder implements IBinder{
}
class Service{
}
class LocalService extends Service {
IBinder b = new LocalBinder();
class LocalBinder extends Binder{
LocalService getService(){
return LocalService.this;
}
}
}
public class BindingTheIsh {
public void tester(IBinder service) {
**LocalService.LocalBinder binder = (LocalService.LocalBinder) service;** // <-- this line fails at run-time
}
public static void main(String[] args) {
IBinder iBinder = new IBinder(){
};
BindingTheIsh b = new BindingTheIsh();
b.tester(iBinder);
}
}