1

I've heard here and there that arrays contain runtime data about their type, making you unable to instantiate an E[] (E being a generic type parameter, for example in a class Foo<E>), and that while you can achieve the same effect by doing (E[]) new Object[n], it is bad, which is why the compiler raises a warning. I'm having trouble thinking of what exactly could go wrong (famous last words), so could someone give an example of how a program could become defective because of instantiating Object[]s and casting them to E[]?

  • You might want to edit to indicate that E is a generic type parameter. – Erik Eidt Sep 15 '16 at 1:49
  • 2
    What is the X Y Problem? – Robert Harvey Sep 15 '16 at 2:43
  • @RobertHarvey My problem is my computer science professor telling his class to create E[] by casting Object[] – Phoenix Sep 15 '16 at 2:47
  • 1
    Do what your teacher says to pass the class. Do it the right way later. See also stackoverflow.com/a/30096771 – Robert Harvey Sep 15 '16 at 2:53
  • He's not requiring us to do that, he's just suggesting it as a good practice. – Phoenix Sep 15 '16 at 2:57
3

If the array is only used within the inside of the class, and the fact of the variable's type as E[] is never exposed outside the class (e.g. returned in a method, or it is a public or protected field, etc.), then there is no problem as inside the class E is erased.

However, if you expose the fact of the array variable's type as E[] to the outside of the class, then it can go into a context where they have a concrete type for your E, and rightly believe that what they are getting is that type of array, and it will throw a ClassCastException without any warning in that outside code. The simplest example is a method that simply returns the array as E[], and it is called from outside code that has a concrete type as the type parameter; a ClassCastException is thrown from the outside code without any warning in that outside code or in the method that returns the array:

public class Foo<E> {

    private E[] myArray = (E[])new Object[42];

    public E[] getArray() {
        return myArray;
    }

}

// some outside code:
Foo<String> foo = new Foo<String>();
String[] stringArray = foo.getArray(); // ClassCastException
|improve this answer|||||
0

You could, of course, declare the array as Object[], and write a private accessor like

Object[] elements = ...;

@SuppressWarnings("unchecked")
private E getElement(int index)
{
    return (E)elements[index];
}

This way, you don't have a field with declaration that lies to you and every other reader of your code, and confine the cast to a single place. The cast is a no-op, btw., because there's no way for the compiler to do a real actual cast to a non-reified type.

This is in fact exactly what goes on inside many well-written collection implementations.

The cast to E[] can have performance benefits for a real actual collection, so it is the way to go in those few places where you write code that influences lots of other code, performance-wise.

Use comments, because exceptional things are the one area where they can be valuable. Restrain the field's scope. Think thrice about what you're doing in any step, and you should be fine :)

In case performance is NOT paramount, though, just use the accessor 😬

|improve this answer|||||
  • I just looked inside a collection I've recently written, and I also used a cast to E[] 😂 – yeoman Sep 15 '16 at 6:07
  • Will change that immediately... – yeoman Sep 15 '16 at 6:07
  • Nope, i take that back. There's been performance reasons for casting to E[]. So just be careful about it :) – yeoman Sep 15 '16 at 6:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.