wood burning stoves 2.0*
The moose likes Java in General and the fly likes downcasting ClassCastException for some java versions. Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "downcasting ClassCastException for some java versions. " Watch "downcasting ClassCastException for some java versions. " New topic
Author

downcasting ClassCastException for some java versions.

Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
I'm facing issues with java runtime errors for version 1.6.34 , Any version below 1.6.31 works fine.

Class SuperA { } // Part of Java awt Package

Class SuperB() extends SuperA{} // Part of Java awt Package

Class SubA extends SuperB { }

Code that was working previously in older Java versions :

SuperA supera = new SuperA();

SubA suba = (SubA) SuperA.getSuperA(); //This returns the current SuperA instance of for the calling thread's context

This line throws ClassCastException now.


I tried different ways of downcasting like

SuperA supera = SuperA.getSuperA();
if((supera != null )&& (supera instanceof SubA)){ // do something}

In this case (supera instanceof SubA) returns false, but (supera instanceof SuperB) returns true.


Can somebody help me code this the correct way?
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4167
    
  21

Are you talking about specific and real classes in the Java AWT package? If so, please tell us what actuall classes you are working with.

It looks to me like you are assuming the value returned from supera.getSuperA() is actually a SubA type, and this may have been true in the past. But the method interface does not require it to be such, and in the current implementation the object returned by SuperA is, in fact, not a SubA. No amount of casting will make it what it is not. This is why you don't program to the implementation (SubA), you program to the interface (SuperA) because the implementation might change and you would be left high and dry when it does.


Steve
Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
Steve Luke wrote:

It looks to me like you are assuming the value returned from supera.getSuperA() is actually a SubA type, and this may have been true in the past.


SuperA.getSuperA(); returns an instance of SuperA , this is a static method in SuperA class .
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4167
    
  21

Stanley Stoffers wrote:
SuperA.getSuperA(); returns an instance of SuperA , this is a static method in SuperA class .


So why are you trying to cast it to a SubA? Edit: and why do you expect it not to give you an error.

And again, what actual classes are you working with in the java.awt package?
Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
SuperA is KeyboardFocusManager

SuperB is DefaultKeyboardFocusManager.

I expect the casting to work because

a) it works in older version

b) Class SubA extends DefaultKeyboardFocusManager which extends KeyboardFocusManager
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4167
    
  21

Stanley Stoffers wrote:SuperA is KeyboardFocusManager

SuperB is DefaultKeyboardFocusManager.

I expect the casting to work because

a) it works in older version

b) Class SubA extends DefaultKeyboardFocusManager which extends KeyboardFocusManager


For b: Just because SubA IS-A KeyboardFocusManager, doesn't mean every KeyboardFocusManager IS-A SubA. So that isn't a reason to think the downcast should work.

For a: Is there any documentation which indicates that it does or should have worked even in the old version? Or were you relying on an undocumented fact? I ask this because it gets back to your issue: You should only program against what is written as the contract between the method writer and the method user - that contract strictly speaking is the method signature (which is to say you should never try to downcast from KeyboardFocusManager, because that is what the method returns) but usually also includes the method documentation (so if the documentation tells you that you can downcast, then you can usually count on it).

If the documentation tells you there are cases when you can downcast safely to whatever SubA is, then you have to figure out why that case has changed in your setup. Was the change documented?

My guess is that the only solution to your problem is to stop using SubA as a reference type, since what you get is not a SubA. Just write your code against the KeyboardFocusManager interface.
Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
Steve Luke wrote:
For a: Is there any documentation which indicates that it does or should have worked even in the old version? Or were you relying on an undocumented fact?


When I build the code using JDK 1.6.31 , it works fine , any version higher and I get the compile time error. Any ideas on why this could be ?
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

It could be because the JVM code changed in the more recent versions.

In fact that's almost certainly why.

But as already pointed out, you don't need to know why (not that knowing why would help you anyway), you just need to fix your program to assign the result of that method call to a KeyboardFocusManager variable, as you should have done in the first place.
Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
Paul Clapham wrote: you just need to fix your program to assign the result of that method call to a KeyboardFocusManager variable, as you should have done in the first place.


Could you please elaborate on this ?

I'm calling a method in subA That is also defined in class KeyboardFocusManager.

Are you saying , I should first call this method using the instance of SubA and then somehow assign it to KeyboardFocusManager ?
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

I'm sorry, I thought that "SubA" was a hypothetical class which you were using just to illustrate your problem. But now it appears you actually have a class named "SubA" in your code. I find that hard to believe -- could you clarify what's going on here?
Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
SuperA supera = new SuperA();

SubA suba = (SubA) SuperA.getSuperA();
// SuperA.getSuperA(); returns the current SuperA instance of for the calling thread's context

then suba is used to call a method in class SubA.

I'm downcasting here and I get a compile time error ClassCastException.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Seriously? You have a class called "SuperA"?
Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
Paul Clapham wrote:Seriously? You have a class called "SuperA"?


No SuperA , SuperB and SubA are just names I gave to illustrate.
Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
Ok Here is what I think I should do , let me know if that will work

SuperA supA = new SubA();

((SubA)supA.getCurrent()).getData();

supA.getCurrent() will return instance of SuperA
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Stanley Stoffers wrote:Ok Here is what I think I should do , let me know if that will work


I have no idea whether it will work or not. How should I know? Just try it and see what happens.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4167
    
  21

No, you should do:


Forget about SubA (or whatever its real name is). It is not something you should be using.
Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
But that won't work because getData() method is only available in SubA class.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4167
    
  21

Stanley Stoffers wrote:But that won't work because getData() method is only available in SubA class.


So what class is SubA - real name please.
Stanley Stoffers
Greenhorn

Joined: Aug 27, 2012
Posts: 13
Steve Luke wrote:
Stanley Stoffers wrote:But that won't work because getData() method is only available in SubA class.


So what class is SubA - real name please.


Well, it is a custom class that extends DefaultKeyboardFocusManager.
Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4167
    
  21

It is a class you wrote that extends DefaultKeyboardFocusManager?

How does it get to be the registered KeyboardFocusManager, such that KeyboardFocusManager.getCurrentKeyboardFocusManager() would ever return your custom implementation?My guess is somewhere you had been doing and either that code is no longer being called, or it is being replaced by some other KeyboardFocusManager. So you should attack it from that side of things...

One alternative is to handle the situations where the current keyboard focus manager isn't what you expect it to be, and replace it with your current one (for example, use instanceof to test if the value returned is your custom implementation or not).

But I still think that is bad design... If the method is not in the KeyboardFocusManager class, then you shouldn't be relying on a KeyboardFocusManager to provide you with that method. You may be trying to do too much with your implementation, and you might be better off separating your concerns (do the KeyboardFocusManager work in one class, and this non-KeyboardFocusManager work in a different class). That may not be feasible or appropriate, but at the very least you should have access to that method some other way (other than through the KeyboardFocusManager.getCurrentKeyboardFocusManager() method), through some other reference so you don't have to worry about casting...

I can't guess at the best route to take here, though, because I don't know your situation. But take a look around your code and see if you can:
1) find a better place where that method belongs
2) or a better way of storing the object which has the method, such that you know how to get directly to it, you know its type, and you don't have to cast it
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: downcasting ClassCastException for some java versions.
 
Similar Threads
Objects of abstract class
Dynamic Casting to subclass
Confused
Inheritance Doubt??
super of super