0

I'm trying to define an array for 3 ArrayLists, each containing a double array. I've used the following syntax:

ArrayList<double[]> testSamples[] = new ArrayList[] {
    new ArrayList<double[]>(), new ArrayList<double[]>(), new ArrayList<double[]>()
};

However this generates a "warning: [unchecked] unchecked conversion" warning when I compile the code. Note: the code works fine, I'm just tried to fix my syntax (correctly) to resolve the warning. Since the code works, it appears to be supported by Java, I'm baffled as to why I can't write something like (which generates a compile error):

ArrayList<double[]> testSamples[] = new ArrayList<double[]>[] {
        new ArrayList<double[]>(), new ArrayList<double[]>(), new ArrayList<double[]>()
};

What am I doing wrong?

JJ.
  • 5,155
  • 3
  • 23
  • 30
  • Yes it compiles and runs ok, however the compiler outputs the given warning. – JJ. Jan 10 '14 at 18:43
  • You can't create an array of parameterized types. Check this post http://stackoverflow.com/q/18581002/1679863 for further explanation. – Rohit Jain Jan 10 '14 at 18:43
  • An `ArrayList`, that takes type `double`, being initialized by several `ArrayList` types? – christopher Jan 10 '14 at 18:44
  • @RohitJain Although he isn't doing that in his snippet. – arshajii Jan 10 '14 at 18:45
  • Your array creation expression is not parameterized , it is raw, which is why you get the warning. – Sotirios Delimanolis Jan 10 '14 at 18:46
  • @JJ. Actually, you're not creating an array of parameterized type, but an array of raw type. And that is why you are getting unchecked warning. And you can't get rid of it. Either use a `List` of `List`, or use the alternative as given by @arshaji. – Rohit Jain Jan 10 '14 at 18:46
  • @SotiriosDelimanolis Granted, I'm pretty sure `new Arraylist[]` throws a compile error. – Dennis Meng Jan 10 '14 at 18:47

2 Answers2

4

You're implicitly converting from an array of the raw type ArrayList to an array of ArrayList<double[]>s. All in all, you shouldn't do something like this. If you know you will have 3 lists, then you can create a class to hold them instead:

class Container {
    private ArrayList<double[]> list1;
    private ArrayList<double[]> list2;
    private ArrayList<double[]> list3;

    ...  // constructors and whatnot

    public ArrayList<double[]> getList(int i) {  // analog of testSamples[i]
        switch (i) {
        case 0:
            return list1;
        case 1:
            return list2;
        case 2:
            return list3;
        default:
            throw new IllegalArgumentException();
        }
    }
}

If the number of lists isn't fixed at 3, then you can use a List<ArrayList<double[]>> instead.

arshajii
  • 118,519
  • 22
  • 219
  • 270
  • 1
    Much better alternative. – Sotirios Delimanolis Jan 10 '14 at 18:45
  • This is definitely easier on the eyes, however the collections are being read and written within loops, and I wanted to avoid using if/switch statements to determine which collection variable to read/write. The code is much more concise if I can just write testSamples[i]. – JJ. Jan 10 '14 at 18:48
  • @JJ. See the edit -- now you can simply do `container.get(i)`. – arshajii Jan 10 '14 at 18:51
  • Sure, refactoring the switch logic into a separate method helps but is still a workaround for a warning that seems to not matter (the code works fine). If no one else solves the original problem you'll get the credit. – JJ. Jan 10 '14 at 18:53
  • @JJ. The code may work as-is but it's terrible practice. In any case, if all you care about is the warning itself, then you can simply use `@SuppressWarnings`. But again, this just hides the underlying problem. – arshajii Jan 10 '14 at 18:56
  • Terrible practice? Why? And no, I don't consider using `@SuppressWarnings` as a solution for this or anything - if I did I wouldn't be asking the question. – JJ. Jan 10 '14 at 18:58
  • @JJ. It's terrible practice primarily because it uses raw types, [which is bad](http://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it). Not to mention it's just bad design to have a `ArrayList[]` -- the data should be encapsulated in classes instead. – arshajii Jan 10 '14 at 19:01
  • @arshakii. I was asking how not to use raw types (and therefore resolve the compiler warning). I'm using a third party API which returns a series of double[] values. The code I'm writing is intended to generate Objects to encapsulate those double[] values as business objects, exactly as you suggest. BTW the number of lists aren't fixed at three elements - they are variable depending on user input. – JJ. Jan 10 '14 at 19:06
  • @JJ. You can't create an array of a parametrized type. The other alternative I can think of (since the number of lists isn't fixed) would be to use a `List>` instead, as I've edited to note. – arshajii Jan 10 '14 at 19:08
  • @arshajii: thanks, I'm already working on that List vs. array solution. It's still bizarre that Java supports the above (it works fine) but generates a warning that doesn't appear to be fixable. – JJ. Jan 10 '14 at 19:12
  • @JJ. You can go through this answer - http://stackoverflow.com/q/18581002/1679863 for understanding, why is the behaviour like this. – Rohit Jain Jan 10 '14 at 19:17
1

This is the usual problem with creating an array of a parameterized type. Why you cannot use new to create an array of a parameterized type is a long topic that has been covered many times here; it basically has to do with how arrays perform runtime checks on the element types, but runtime checks cannot check type parameters.

Long story short, an unchecked warning of some kind is unavoidable (because it is indeed possible to make it violate the guarantees of the array type). If you don't mind the "unsafeness", the most kosher way to write it is to create the array using a wildcarded type instead of a raw type, and cast it to the proper type of array (yes, this is an unchecked cast):

ArrayList<double[]>[] testSamples =
    (ArrayList<double[]>[]) new ArrayList<?>[] { ... }
newacct
  • 110,405
  • 27
  • 152
  • 217