tags:

views:

143

answers:

4

So I just spent around an hour trying to unveil and resolve a very strange bug, one that I have never seen before.

I am more or less asking for potential causes of this seeming random cast from enum to String rather than "please fix my code for me".

The gist of the problem is as follows:

I have an interface, call it IFoo, within this interface, it has a static enum, called Bar:

public interface IFoo {
  static enum Bar{
    A,
    B,
    C,
  }

  Bar doGetBar();
}

I of course have a Foo class that implements IFoo.

public class Foo implements IFoo{
  public Bar getBar(){
    return Bar.A; // for example
  }
}

Somewhere else, I have an object array called

Object[] result;

And a helper method that returns an array of Objects, holding results from the getBar() method, call it

public Object[] getBars()

Now, when I do

result = getBars();

result magically holds Strings instead of Bars, the values of the strings are the implementation class of the outer class (not really an outer class, more of a wrapper class?) of Bar, i.e. "Foo".

Could someone possibly explain to me how this is possible?

Some leads: 1. results were holding strings before the assignment. 2. the static enum inside IFoo is questionable, it was non-static, but it caused ClassCastExceptions when I tried to cast it to IFoo.Bar from Foo.Bar (or something along these lines).

+3  A: 

Your Object[] has got Strings in it because you put them there. If you post a small example piece of code demonstrating clearly that you put Bars in but get Strings out I will be very surprised.

The method for resolving bugs like this is to start from the beginning, making a simple working example (which will likely not display the bug). Then keep adding code to make it more like your real-world application until the bug rears its head. Then you'll be able to identify your most recent change as the source of the bug.

oxbow_lakes
Well, I looked through the debugger, and evaluated the output of the right hand side directly after the assignment. One was holding String objects, and one was holding enums.
Cambium
There are a few options. 1) you have made a mistake about what you thought you saw in the debugger. 2) you have made a mistake about what code you thought you were executing in the debug step. 3) There is a fundamental issue with the JVM. On your machine. And no-one elses. Take my advice - you need to slowly and methodically recereate your problem from scratch. I know it's a pain. But it **will work**
oxbow_lakes
+2  A: 

Use collections and generics for type safety instead.

Edit As now the question changed to a conceptional level, I'll use my telesense to figure out the cause.

It seems you are reusing an Object[] array on line 252 for completely different purposes. The compiler accepts

Object[] objs = Bar.values();
//...
objs = "A B C".split("\\s+");
//...
return objs;

this kind of code because arrays in Java are covariant (e.g. String[] is subclass of Object[]). Reusing a base class object array this way is troublesome.

kd304
First question: "Why can't I assign an `ArrayList<String>` to `List<Object>`?"?
Tom Hawtin - tackline
Because I don't want it?
kd304
+2  A: 

It's not clear what "magic" is contained within the getBars() method, and without more information, It's not possible to produce a sample implementation to verify this behaviour. Specifically, it's not clear what "a helper method that returns an array of Objects, holding results from the getBar() method" means.

If you can, isolate the smallest test case containing the behaviour, as suggested. oxbow_lakes' suggestion is also good; bring a simple test as close to the real behaviour as possible.

If you really can't produce a simplified scenario to show us, then our ability to help you is going to be severely curtailed, since that getBar() method is where the Object[] is populated. In that case, if you can't work it out, then I suggest you may have to ask a more knowledgeable colleague for a bit of help - could be a second set of eyes will spot it.

Rob
A: 

I am assuming that your getBars() method looks like this:

     public Object[] getBars() {
  return Bar.values();
 }

if you are wondering what you should be receiving from the 'Bar.values()' method, check out the JavaDoc. In your case, values() would return type FooI$Bar.

It might be useful to post, not only the code that you have put together that throws the exception, but the ClassCastException as well.

akf