【问题标题】:ClassCastException Double to FloatClassCastException Double to Float
【发布时间】:2013-03-31 04:24:22
【问题描述】:

由于某种原因,这段代码抛出了ClassCastException,告诉我不能将 Double 转换为 Float。异常来自下面的第一行代码。 mapData.speedsArrayList<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?你确定错误不是来自第二行吗?
  • 你有错误信息的非标准设置吗?你用什么版本的 Java 编译?
  • 不管是float还是wrapper类,Java都会自动拆箱
  • 不,我没有弄乱错误消息设置。我正在使用 1.6 进行编译。

标签: java android casting


【解决方案1】:

我猜你的代码实际上将spd 声明为Float(而不是float)。我也猜测例外来自第二行。尝试将第二行更改为:

spd = (spd * 3600 / 1609.34f);

这将使右侧成为float 而不是double。 Java 中的浮点文字为 double,除非它们以 fF 结尾。

如果我的猜测是准确的,那么异常是由 Java 将 double 值表达式自动装箱到 Double 然后尝试将其强制转换为 Float 以将其分配给变量引起的spd.

玩了一会儿后,我发现我无法复制您的错误消息。您的代码甚至无法编译;编译器在第二行抱怨“错误:可能的精度损失”。所以现在我有另一个猜测:您已经隐藏了该错误消息(或将其设置为警告而不是错误并忽略它)。

【讨论】:

  • 我认为您无法抑制 that 错误消息(“精度损失”)。 JLS 说,在没有类型转换的情况下将 double 分配给 float 是非法代码,任何允许您这样做的编译器都不符合要求。
  • spd 确实是,现在也是,一个原始的。我尝试添加'f',但无济于事。我收到了同样的错误。我什至不知道如何抑制错误或将错误设置为警告,因此怀疑我做到了。
  • @brainmurphy1 - 你能发布异常的堆栈跟踪吗?
  • @brainmurphy1 - 当你在代码的非混淆版本上运行时,你会得到同样的异常吗?
  • 非混淆?我的代码是从 Eclipse 复制到这个页面上的。如果您指的是 google maps android API v2 的东西,我将如何“取消混淆”它?
【解决方案2】:

如果mapData.speeds 真的被声明为ArrayList&lt;Float&gt;,那么获得类强制转换异常的唯一方法就是抑制/忽略一些关于不安全转换的警告。 (在设置speed 属性的代码或将值放入列表的代码中。)

将发生类转换,因为您的代码实际上等同于:

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

mapData.speeds.get 的实际(已删除)签名是 Object get(int)

通常(即,如果您不禁止显示警告)编译器会告诉您,如果您做了一些导致Double 被添加到ArrayList&lt;Float&gt; 的操作。但是,如果您忽略这些警告,您最终可能会得到一个 Double,而应该是 ArrayList&lt;Float&gt;。如果发生这种情况,当您将get 的结果用作float 时,您将得到一个类转换异常。

【讨论】:

  • 据我所知,我没有忽略任何警告,所以我认为我的问题不符合您解决方案的标准。
  • 好的。所以试试这个。 Object spd = mapData.speeds.get(focusPointIndex); System.out.println(spd.getClass()); 我敢打赌它会输出java.lang.Double
  • 是的!这是。这个怎么可能?它被声明为“公共 ArrayList 速度;”在 MapData 类中。
【解决方案3】:

3600/1609.34 更改为3600f / 1609.34f

如果您在代码中使用十进制数,它将被推断为双精度类型。在数字末尾包含 F 以告诉编译器它是浮点数而不是双精度数。

为获得最佳实践,请养成始终以 D 或 F(Double 或 Float)结尾的十进制常量的习惯。 考虑到 Java 让您为了编写最简单的流程而绞尽脑汁,这似乎并不过分。

【讨论】:

  • 我添加了 f。没有改变。不过谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多