Reputation: 1112
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)
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
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 i
th 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
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
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
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