出于某种原因,这段代码抛出了一个
ClassCastException
,告诉我无法将 Double 转换为 Float。异常源自下面的第一行代码。 mapData.speeds
是ArrayList<Float>
。
双子在哪里?
float spd = mapData.speeds.get(focusPointIndex);
spd = (spd * 3600/1609.34);
这是完整的堆栈跟踪:
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)
我想我已经找到导致错误的原因,但仍然不知道为什么会发生,或者如何修复它。我正在从 JSON 中解析 mapData 对象,因为它包含许多不同类型的 ArrayList,所以我创建了一个方法,将 JSONArray 解析为指定类型的 ArrayList。方法如下
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;
}
我猜测您的代码实际上将
spd
声明为 Float
(而不是 float
)。我还猜测例外是来自第二行。尝试将第二行更改为:
spd = (spd * 3600 / 1609.34f);
这将使右侧成为
float
而不是 double
。 Java 中的浮点文字是 double
,除非它们以 f
或 F
结尾。
如果我的猜测是准确的,则异常是由于 Java 将
double
Double
,然后尝试将其转换为 Float
以将其分配给变量 spd
引起的。 玩了一下后,我发现我无法复制您的错误消息。你的代码甚至无法编译;编译器在第二行抱怨“错误:可能丢失精度”。所以现在我有另一个猜测:您已经抑制了该错误消息(或者将其设置为警告而不是错误并忽略它)。
如果
mapData.speeds
确实被声明为 ArrayList<Float>
,那么获得这样的类转换异常的唯一方法是如果您抑制/忽略了一些有关不安全转换的警告。 (在设置 speed
属性的代码中或在将值放入列表中的代码中。)
类转换将会发生,因为你的代码实际上相当于这样:
Float tmp = (Float) (mapData.speeds.get(focusPointIndex));
float spd = tmp.floatValue();
并且
mapData.speeds.get
的实际(已删除)签名是 Object get(int)
。
通常(即,如果您不抑制警告)编译器会告诉您,如果您执行的操作会导致 Double
添加到
ArrayList<Float>
中。 但是,如果您忽略这些警告,您最终可能会得到一个 Double
,而本该是 ArrayList<Float>
。 如果发生这种情况,当您使用 get
的结果作为 float
时,您将收到类转换异常。3600/1609.34
更改为
3600f / 1609.34f
如果您在代码中使用十进制数,它将被推断为 double 类型。 在数字末尾添加 F 来告诉编译器它是浮点型而不是双精度型。
为了获得最佳实践,请养成始终以 D 或 F(双精度型或浮点型)结尾十进制常量的习惯。 考虑到 Java 让你绞尽脑汁只为了写出最简单的流程,这看起来似乎并不算大材小用。
TL:博士;这是一个简单的类型转换问题。
让我们首先简要查看一下编辑中添加的代码示例,之前的响应没有对此做出反应。这个标题有点问题:
<T> ArrayList<T> JSONArrayToList(JSONArray jsonArr);
它是一个泛型方法,但它没有泛型参数。因此,类型信息的唯一来源是调用本身:基本上,类型信息仅来自旁观者的眼睛。
这意味着当尝试
arrList.add((T)jsonArr.get(i))
时,将从 JSON 数组的第
i
元素中选取一个元素,然后将其类型转换为从调用中推断出的任何类型。Java 具有相当好的类型安全性,与 JavaScript 等语言相比,它动态转换类型的方法并不那么自由。由于 JSON 明显包含 Double
并且该方法的结果被添加到
List<Float>
,因此尝试强制转换失败并完成。为缺乏经验的开发人员提供强类型语言和 JSON。会出什么问题吗?