2

For some reason, this code is throwing a ClassCastException, telling me that I cannot cast a Double to a Float. The exception emanates from the first line of code below. mapData.speeds is an ArrayList<Float>. Where is the Double?

float spd = mapData.speeds.get(focusPointIndex);
spd = (spd * 3600/1609.34);

Here is the complete stack trace:

03-31 01:00:51.008: E/AndroidRuntime(17778): FATAL EXCEPTION: main
03-31 01:00:51.008: E/AndroidRuntime(17778): java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Float
03-31 01:00:51.008: E/AndroidRuntime(17778):    at net.taptools.android.trailtracker.ResultsMapViewingFragment$4.onMapLongClick(ResultsMapViewingFragment.java:224)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at com.google.android.gms.maps.GoogleMap$5.onMapLongClick(Unknown Source)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at com.google.android.gms.internal.k$a.onTransact(Unknown Source)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at android.os.Binder.transact(Binder.java:326)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at com.google.android.gms.maps.internal.IOnMapLongClickListener$Stub$Proxy.onMapLongClick(IOnMapLongClickListener.java:93)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at maps.i.s.a(Unknown Source)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at maps.y.v.d(Unknown Source)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at maps.y.bf.onLongPress(Unknown Source)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at maps.d.v.onLongPress(Unknown Source)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at maps.d.h.c(Unknown Source)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at maps.d.h.c(Unknown Source)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at maps.d.j.handleMessage(Unknown Source)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at android.os.Handler.dispatchMessage(Handler.java:99)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at android.os.Looper.loop(Looper.java:137)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at android.app.ActivityThread.main(ActivityThread.java:5059)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at java.lang.reflect.Method.invokeNative(Native Method)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at java.lang.reflect.Method.invoke(Method.java:511)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
03-31 01:00:51.008: E/AndroidRuntime(17778):    at dalvik.system.NativeStart.main(Native Method)

--edit--

I think I have found what has caused the error, but still do not know why it is occurring, or how to fix it. I am parsing the mapData Object out of JSON, and because it contains many ArrayLists of various types, I created a method that will parse a JSONArray into and ArrayList of a designated type. Here is the method.

private <T> ArrayList<T> JSONArrayToList(JSONArray jsonArr){
        ArrayList<T> arrList = new ArrayList<T>();
        for(int i = 0; i<jsonArr.length(); i++){
            try {
                arrList.add((T)jsonArr.get(i));
            } catch (JSONException e){e.printStackTrace();}
        }
        return arrList;
    }
5
  • 1
    Is spd declared to be a float or a Float? And are you absolutely sure that the error is not from the second line? Commented Mar 31, 2013 at 4:27
  • Do you have any non-standard settings for error messages? What version of Java are you compiling with? Commented Mar 31, 2013 at 4:45
  • It wouldn't matter if it's a float or the wrapper class, Java will auto-unbox it Commented Mar 31, 2013 at 5:27
  • no, I haven't messed with the error message settings. I am compiling with 1.6. Commented Mar 31, 2013 at 5:33
  • Ah, mobile development. Give a relatively unexperienced developer a strongly typed language and a JSON array that can contain anything. What could go wrong ... except for the part with attempting a typecast. Commented Nov 1, 2024 at 21:33

4 Answers 4

4

I'm guessing that your code actually declares spd to be a Float (rather than a float). I'm also guessing that the exception is from the second line. Try changing the second line to:

spd = (spd * 3600 / 1609.34f);

That will make the right side a float rather than a double. Floating point literals in Java are double unless they end in f or F.

If my guesses are accurate, the exception is being caused by Java autoboxing the double-valued expression to a Double and then trying to cast it to a Float in order to assign it to variable spd.

After playing around a bit, I find that I cannot duplicate your error message. Your code won't even compile; the compiler complains "error: possible loss of precision" on the second line. So now I have another guess: you've suppressed that error message (or set it to be a warning instead of an error and are ignoring it).

Sign up to request clarification or add additional context in comments.

7 Comments

I don't think you can suppress that error message ("loss of precision"). The JLS says that assigning double to float without a typecast is illegal code, and any compiler that allowed you to do that would not be compliant.
spd really was, and is, a primitive. I tried adding the 'f', but to no avail. I received the same error. I do not even know how to suppress errors or set an error as a warning, and thus doubt that I did.
@brainmurphy1 - Can you post the stack trace for the exception?
@brainmurphy1 - Do you get the same exception when you run on a non-obfuscated version of your code?
non obfuscated? My code was copied from Eclipse right onto this page. If you are referring to the google maps android API v2 stuff, how would I 'unobfuscate' it?
|
2

If mapData.speeds is really declared as an ArrayList<Float> then the only way you can get a class cast exception like that is if you have suppressed / ignored some warnings about unsafe conversions. (Either in the code that sets the speed attribute or the code that puts values into the list.)

The class cast will be happening because your code is actually equivalent to this:

Float tmp = (Float) (mapData.speeds.get(focusPointIndex));
float spd = tmp.floatValue();

and the actual (erased) signature of mapData.speeds.get is Object get(int).

Normally (i.e. if you don't suppress the warnings) the compiler will tell you if you do something that would result in a Double being added to an ArrayList<Float>. However, if you ignore those warnings you can end up with a Double in what is supposed to be an ArrayList<Float>. If that happens, you will get a class cast exception when you use the result of the get as a float.

3 Comments

I didn't ignore any warnings as far as I know, so I don't think my problem meets the criteria of your solution.
OK. So try this. Object spd = mapData.speeds.get(focusPointIndex); System.out.println(spd.getClass()); I bet it outputs java.lang.Double.
yes! It is. How can that be? It is declared as "public ArrayList<Float> speeds;" in the MapData class.
0

Change 3600/1609.34 to 3600f / 1609.34f

If you use a decimal number in your code it will be inferred as a type double. Include an F at the end of the number to tell the compiler it's a float not a double.

For best practice, make a habit of always ending your decimal constants with a D or F (Double or Float). It shouldn't seem like overkill considering that Java makes you type your brains out just to write the simplest flow.

1 Comment

I added the f's. Nothing changed. Thanks though
0

I might be 11 years too late, by now either the problem has been solved by OP (without sharing it here) or the company the dev works for has became defunct.

TL:DR; it's a simple typecast problem.

Let's start by having a brief look at the code sample that was added in the edit, that previous responses didn't react to. The very header is somewhat problematic:

<T> ArrayList<T> JSONArrayToList(JSONArray jsonArr);

It is a generic method, but it has no generic argument. So, the only source of the type information is from the call itself: Basically, the type information comes solely from the eye of the beholder.

That means that when arrList.add((T)jsonArr.get(i)) is attempted, an element is picked from ith element of a JSON array, and then it's type-casted to whatever type was inferred from the call.

Java has pretty good type safety, and compared to languages like JavaScript, it is not as freestyle in its approach to converting types on the fly. Since the JSON clearly contains a Double and the method's result is being added to a List<Float>, the attempt to cast fails and it's done.

Give a somewhat inexperienced developer a strongly typed language, and JSON. What could go wrong?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.