为什么在Java中无法将float []转换为double []?

时间:2018-08-07 16:07:44

标签: java types casting

我正在使用一个API,该API结果返回二维float数组。我想使用流API中的flatMap方法处理此数据,但需要将double数组传递到其方法中。我试图通过将float[][]强制转换为double[][]来解决此问题,但是即使使用float[]也无法解决。这是一个JShell会话转储:

-> new float[] {1.02f, 4.32f, 65.4f}
  Expression value is: [F@2b98378d
    assigned to temporary variable $1 of type float[]

-> double[] arrayOfDoubles = (double[]) $1
  Error:
  incompatible types: float[] cannot be converted to double[]
  double[] arrayOfDoubles = (double[]) $1;

因此,我的问题是:当从float[]投射到double[]是合法的时候,为什么我们不能将float投射到double

2 个答案:

答案 0 :(得分:5)

如果要查看float[] 占据的存储空间,就好像它是double[],那么数组中的偏移量将是全部错误的。因此,当您查看双重#1时,您会看到#1浮点数和#2浮点数的一部分。这就是为什么您需要转换,而不仅仅是转换。

换句话说,Java语言规范根本不提供与转换相关的语法形式的转换。

回到原来的问题,这里是Brian Goetz的一个很好的技巧:

DoubleStream ds = IntStream.range(0, floatArray.length)
                       .mapToDouble(i -> floatArray[i]);

最后,通过上述技巧,这是您的flatMap DoubleStream:

DoubleStream ds = Arrays.stream(float2dArray)
        .flatMapToDouble(floatArray -> IntStream.range(0, floatArray.length)
                .mapToDouble(i -> floatArray[i]));

答案 1 :(得分:5)

数组是引用类型,甚至是具有基本元素的数组。

强制引用类型实际上对基础对象没有任何作用:它只是告诉编译器“相信我,我比你知道更多类型信息:对Foo的引用可以安全地处理作为对酒吧的参考”。

除非编译器可以证明强制类型转换不安全,否则它会信任您并允许您执行;由程序员(程序员)来检查它是否安全,或者在运行时面临ClassCastExceptions。

因此,将float[]强制转换为double[]不会更改基础对象,它只会更改编译器允许您对其进行的操作。

但是一旦您可以将其视为double[],就可以要求JVM将double分配给该数组的元素。 double不适合float,因此有两种选择:

  • 检查该值是否在范围内,然后进行强制转换。但是,这样一来,您将失去精度,而调试起来可能会非常困难;
  • 或者,从一开始就阻止您将float[]分配给double[],以阻止您陷入困境。

第二个选择更简单,那就是他们做出的选择。


请注意,您可以通过float[]进行投射,从而将double[]投射到Object

float[] f = ...
double[] d = (double[]) (Object) f;

这将在运行时失败,除非f为空。