szymon
szymon

Reputation: 61

Why is it not possible to cast float[] to double[] in Java?

I'm using an API that returns two-dimensional float array as a result. I'd like to process this data using the flatMap method from the streaming API, but I need to pass arrays of doubles into its methods. I've tried to work it around by casting float[][] into double[][], but it didn't work, even with float[]. Here's a JShell session dump:

-> 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;

So, my question is: why can't we cast float[] into double[], when it's fairly legal to cast from float to double?

Upvotes: 5

Views: 1723

Answers (2)

Patrick Parker
Patrick Parker

Reputation: 4959

If you were to look at the memory space inhabited by a float[] as if it were double[], then the offsets into the array would be all wrong. So you would be seeing part of float #1 and float #2 when you look at double #1. That's why you need conversion, not just casting.

Put another way, the Java Language Specification simply doesn't supply such a conversion in the form of casting related syntax.

Getting back to your original problem, here is an excellent tip from Brian Goetz:

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

And finally, here is your flatMap DoubleStream, via the above trick:

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

Upvotes: 6

Andy Turner
Andy Turner

Reputation: 140318

Arrays are reference types, even arrays with primitive elements.

Casting reference types doesn't actually do anything to the underlying object: it merely tells the compiler "trust me, I know more type information than you: this reference to a Foo can be safely treated as a reference to a Bar".

Unless the compiler can prove that the cast is unsafe, it trusts you and lets you do it; it is on you, the programmer, to check that it is safe, or face ClassCastExceptions at runtime.

So, casting a float[] to a double[] doesn't change the underlying object, it merely changes what the compiler lets you do with it.

But once you can treat it like a double[], you can ask the JVM to assign a double to an element of that array. double doesn't fit in float, so there are two choices:

  • Check if the value is in range, and cast. But then you lose precision, in a way that will be potentially very hard to debug;
  • Or, stop you getting into the situation in the first place by preventing you assigning a float[] to a double[].

The second choice is simpler, and that is the choice they made.


Note that you can cast a float[] to a double[], by casting via Object:

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

This will fail at runtime, however, unless f is null.

Upvotes: 6

Related Questions