1

I want to create a two-dimensional array (yes I know that this is actually an array of arrays) holding Optionals. The normal approach for generic array creation does not work though as it fails with a ClassCastException. Here is my code:

@SuppressWarnings("unchecked")
Optional<Integer>[][] arr = (Optional<Integer>[][]) new Object[5][5];

Is there a way to create such an array, if yes what would be the approach for that?

2
  • Why would you want to do that? To me it doesn’t sound like a standard or recommended use of Optional. Commented Jan 14, 2019 at 9:41
  • 1
    @Ole V.V I do agree that this is not the intended use of Optional and I do not use it this way. I was just curious if this would work, as my code failed to do so. Commented Jan 14, 2019 at 23:06

2 Answers 2

1

In Java "it is illegal to create an array of a generic type, a parameterized type, or a type parameter". "Why is it illegal to create a generic array? Because it isn’t typesafe. If it were legal, casts generated by the compiler in an otherwise correct program could fail at runtime with a ClassCastException. This would violate the fundamental guarantee provided by the generic type system." [Joshua Bloch - Effective Java]

So what solutions are to be able to create multidimensional arrays?

The recommended one would be to use a container:

List<List<Optional<Integer>>> arr = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    arr.add(new ArrayList<Optional<Integer>>());
}
Sign up to request clarification or add additional context in comments.

Comments

0

Generics aside, you can't cast an Object[][] to a raw-typed Optional[][]. You'll get a ClassCastException at runtime. The array has to be created as an Optional[][], not as Object[][]. But generics are usually preferred raw types.

It's not that you can never create arrays of generics. You have to do so indirectly. Typically the way to do it is to create arrays of unbounded-wildcard generics, and then do an unchecked cast -- as you've done -- to the right type:

@SuppressWarnings("unchecked")
Optional<Integer>[][] arr = (Optional<Integer>[][]) new Optional<?>[5][5];

The above applies to the creation of any arrays of some specific generic type. In this case, you might consider using OptionalInt instead of Optional<Integer>. This bypasses any concerns about arrays of generics.

(Overall I'm somewhat suspicious of the notion of creating arrays or collections of Optionals of any flavor. It just seems like an odd thing to do. There are often better alternatives. But it might be justified in some cases. Anyway, whether an array of Optionals is appropriate for whatever problem you're trying to solve is a separate question.)

2 Comments

So in general a cast from a wildcard to the actual type is needed, when creating an array of parameterized type?
@Vajk Yes, you have to create the array with either a raw type or an unbound wildcard generic type, and then cast it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.