Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 533
szymon Avatar asked Aug 07 '18 16:08

szymon


People also ask

Can we cast float to double in Java?

The doubleValue() method of Java Float class returns a double value corresponding to this Float Object by widening the primitive values or in simple words by directly converting it to double via doubleValue() method .

Can float convert to double?

floatValue() to Convert Double to Float in Java. Another way to convert a double value into a float data type in Java is by using the wrapper class Double. This class wraps a primitive data type double in an object.

Is addition of float and double is possible without typecasting?

Doubles are more precise and the extra storage cost is almost always negligible. So in Java by default 2.1 is a double type. Now to convert double to float you need to cast while assigning double data to double type cast is not required.


2 Answers

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.

like image 169
Andy Turner Avatar answered Nov 15 '22 04:11

Andy Turner


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]));
like image 42
Patrick Parker Avatar answered Nov 15 '22 04:11

Patrick Parker