0

When I declare the Array of ArrayLists below, it compiles correctly but has a warning stating, "Unchecked or Unsafe operations." Node is an inner class that I created within my public class.

private ArrayList<node>[] arr = new ArrayList[5];

I already tried both of the following, neither of which compiled:

private ArrayList<node>[] arr = new ArrayList<node>[5]; 
private ArrayList<node>[] arr = new ArrayList<>[5];

What is the issue here? Thank you for any help.

tony2112_
  • 3
  • 2
  • 2
    Possible duplicate of [What causes javac to issue the "uses unchecked or unsafe operations" warning](https://stackoverflow.com/questions/197986/what-causes-javac-to-issue-the-uses-unchecked-or-unsafe-operations-warning) – Carcigenicate Oct 28 '18 at 23:45
  • You're getting that warning because of raw types, but I forgot you can't easily create arrays of generic types (thus my erroneous previous comment). That dupe explains the warning, but [this](https://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java) explains how to create a generic array. Do you really need an array though? A 2D ArrayList isn't sufficient? – Carcigenicate Oct 28 '18 at 23:56

2 Answers2

0

Generic types are non-refied. That is they are fictitious and not available at run time. For an instance ArrayList<String> becomes ArrayList at run time. All the generic information is erased at the time you compile the code.

On the other hand arrays are refied, meaning they have more information retained at run time. So in run time all you have is new ArrayList[5]. That's why compiler does not allow this.

These operations are illegal because they are not type safe.

private ArrayList<node>[] arr = new ArrayList<node>[5]; 
private ArrayList<node>[] arr = new ArrayList<>[5];

If it were legal, casts generated by the compiler could fail at runtime. This will violate the fundamental guarantee provided by the generic type system.

Ravindra Ranwala
  • 18,704
  • 6
  • 38
  • 55
0

Arrays know their component type at runtime and every time you set a non-null reference on an array, it checks at runtime, that the object the reference points to is an instance of the array's component type; if it isn't, it's guaranteed to throw an ArrayStoreException.

Object[] foo = new Integer[42];
foo[0] = "bar"; // throws ArrayStoreException -- "bar" is not an instance of Integer

However, it's not possible to check that an object is an instance of a parameterized type, since objects do not know their type arguments at runtime. It's only possible to check that an object is an instance of a reified type at runtime; and that's why array component types are only allowed to be reified types.

You can still create an array of the raw type and assign it to the type of array of the parameterized type, as you are doing:

private ArrayList<node>[] arr = new ArrayList[5];

Or you can create an array of the unbounded wildcard type (which is also reified) and then explicitly cast it to the type of array of the parameterized type:

private ArrayList<node>[] arr = (ArrayList<node>[])new ArrayList<?>[5];

In both cases there will be an unchecked warning. By giving you a warning, that means you take responsibility for bad things that might happen. For example:

Object[] foo = arr;
foo[0] = new ArrayList<String>(); // no ArrayStoreException -- it is an instance of ArrayList
// now you have an ArrayList<node>[] that contains an ArrayList<String>
user102008
  • 28,544
  • 10
  • 78
  • 100