brainmurphy1
brainmurphy1

Reputation: 1112

ClassCastException Double to Float

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;
    }

Upvotes: 2

Views: 7540

Answers (4)

Vlasec
Vlasec

Reputation: 5546

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?

Upvotes: 0

mrres1
mrres1

Reputation: 1155

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.

Upvotes: 0

Stephen C
Stephen C

Reputation: 719576

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.

Upvotes: 2

Ted Hopp
Ted Hopp

Reputation: 234857

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).

Upvotes: 4

Related Questions