为什么不能在Java中将float []转换为double []?

szy*_*ski 5 java types casting

我正在使用一个返回二维float数组的API .我想使用flatMap来自流API 的方法处理这些数据,但我需要将doubles的数组传递给它的方法.我试图通过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;
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是:为什么我们不能投float[]double[],当它是相当的法律,从投floatdouble

Pat*_*ker 5

如果你看一个人居住的内存空间float[] ,就好像它是double[],那么偏移到数组将是完全错误的.因此,当你看到双#1时,你会看到浮动#1和浮动#2的一部分.这就是为什么你需要转换,而不仅仅是转换.

换句话说,Java语言规范只是不以铸造相关语法的形式提供这种转换.

回到原来的问题,这是Brian Goetz的一个很好的提示:

DoubleStream ds = IntStream.range(0, floatArray.length)
                       .mapToDouble(i -> floatArray[i]);
Run Code Online (Sandbox Code Playgroud)

最后,通过以上技巧,这是你的flatMap DoubleStream:

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


And*_*ner 5

数组是引用类型,甚至是具有原始元素的数组.

转换引用类型实际上对底层对象没有任何作用:它只是告诉编译器"相信我,我知道比你更多的类型信息:这个对Foo的引用可以安全地被视为对Bar的引用".

除非编译器可以证明演员表不安全,否则它会信任你并允许你这样做; 程序员可以检查它是否安全,或者在运行时面对ClassCastExceptions.

因此,将a转换float[]为a double[]不会更改底层对象,它只会更改编译器允许您使用它的内容.

但是,一旦你可以像对待它一样对待它double[],你可以要求JVM将一个double元素分配给该数组.double不适合float,所以有两种选择:

  • 检查值是否在范围内,并进行强制转换.但是你会以一种可能很难调试的方式失去精确度;
  • 或者,阻止你通过阻止你分配一个进入的情况摆在首位float[]double[].

第二种选择更简单,这就是他们做出的选择.


请注意,您可以施放float[]double[],经由铸造Object:

float[] f = ...
double[] d = (double[]) (Object) f;
Run Code Online (Sandbox Code Playgroud)

但是,这将在运行时失败,除非f为null.