A new helper method Arrays.asArray
forax at univ-mlv.fr
forax at univ-mlv.fr
Wed Jun 15 06:56:39 UTC 2016
----- Mail original -----
> De: "timo kinnunen" <timo.kinnunen at gmail.com>
> À: forax at univ-mlv.fr
> Cc: "core-libs-dev" <core-libs-dev at openjdk.java.net>, "Louis Wasserman"
> <lowasser at google.com>
> Envoyé: Mercredi 15 Juin 2016 03:14:46
> Objet: RE: A new helper method Arrays.asArray
> The same issue is present even without any varargs or generics present, when
> using plain old arrays:
> String[] list1 = new String[1];
> list1[0] = "hello";
> Integer[] list2 = new Integer[1];
> list2[0] = 1;
> String[][] array = {list1, null};
> Object[][] array2 = array;
> array2[1] = list2;
> for(String[] l : array) {
> System.out.println(l[0]);
> }
Ok, array are unsafe in Java but there is a *huge* difference between the two codes, here you get a CCE where you make the mistake i.e. where you try to store list2 in array2.
In the code with an array of parameterized type, you get the CCE somewhere after.
With a classical array, the compiler give up on the safety but the VM checks that you are not doing something stupid, with an array of parameterized type, the VM can not do the same check at runtime because generics are not reified at runtime so the VM is not able to make the difference between List<String> and List<Integer> thus it can not throw a CCE where you do an unsafe operation and it will likely throw a CCE elsewhere later. To avoid this nasty behavior, the compiler emit a warning (or an error) when you try to create an array of parameterized type.Usually the right way to solve that issue is to not use an array and not to use @SuppressWarnings or @SafeVarargs.
Rémi
> --
> Have a nice day,
> Timo
> Sent from Mail for Windows 10
> From: forax at univ-mlv.fr
> Sent: Wednesday, June 15, 2016 00:38
> To: timo kinnunen
> Cc: core-libs-dev ; Louis Wasserman
> Subject: Re: A new helper method Arrays.asArray
> > De: "timo kinnunen" <timo.kinnunen at gmail.com>
>
> > À: "Remi Forax" <forax at univ-mlv.fr>
>
> > Cc: "core-libs-dev" <core-libs-dev at openjdk.java.net>, "Louis Wasserman"
> > <lowasser at google.com>
>
> > Envoyé: Mardi 14 Juin 2016 23:39:19
>
> > Objet: RE: A new helper method Arrays.asArray
>
> > I think @SafeVarargs should be OK here since the array containing the
> > varargs
> > already exists before the method starts executing and so the annotation
> > amounts to asserting that the passed-in vararg-array is just as safe during
> > the execution of the method as it is after the method execution completes.
>
> > In any case, I’m only adding it to my versions to silence a compiler
> > warning.
> > In a JDK version the API doc should nail down that the method executes
> > indistinguishable from a method which simply returns the passed-in array
> > and
> > the JDK version can freely choose which annotations to have. I would
> > actually prefer the JDK implementation to use @ForceInline or something
> > like
> > that instead which my versions can’t use. This would guarantee that there
> > is
> > no overhead in calling the method and that type-safety issues present, if
> > any, will occur within the calling context. Which is where they would have
> > been introduced.
>
> Given the code of your method, it will be inlined because the implementation
> is trivial.
> And your code is unsafe because you can have a ClassCastException with no
> warning at a line where you see no cast,far away from where the bug lies,
> List<String> list1 = new ArrayList<>();
> list1.add("hello");
> List<Integer> list2 = new ArrayList<>();
> list2.add(1);
> List<String>[] array = asArray(list1, null);
> List<?>[] array2 = array;
> array2[1] = list2;
> for(List<String> l: array) {
> System.out.println(l.get(0));
> }
> A warning in Java means something goes wrong and the compiler and the VM can
> not help you, forget about @SuppressWarnings or @SafeVarargs and change your
> code if you are not writing a class of java.util or guava.
> cheers,
> Rémi
> > --
>
> > Have a nice day,
>
> > Timo
>
> > Sent from Mail for Windows 10
>
> > From: Remi Forax
>
> > Sent: Tuesday, June 14, 2016 21:43
>
> > To: timo kinnunen
>
> > Cc: core-libs-dev ; Louis Wasserman
>
> > Subject: Re: A new helper method Arrays.asArray
>
> > Hi Timo,
>
> > your implementation can not use @SafeVarargs because you leak the array
> > (you
> > return it) so you're code is not safe because you can not be sure that the
> > resulting array will not be modified after the call to asArray.
>
> > Louis, because you can not create an array of parametrized type in Java :)
>
> > Here, the easy solution is to not create an array but a List,
>
> > List<Comparator<Object>> list = List.of(sort0, sort1);
>
> > or
>
> > List<Comparator<Object>> list = Arrays.asList(sort0, sort1);
>
> > depending if you want a mutable List (but with a fixed size) or an
> > immutable
> > one.
>
> > cheers,
>
> > Rémi
>
> > ----- Mail original -----
>
> > > De: "Louis Wasserman" <lowasser at google.com>
>
> > > À: "timo kinnunen" <timo.kinnunen at gmail.com>, "core-libs-dev"
> > > <core-libs-dev at openjdk.java.net>
>
> > > Envoyé: Mardi 14 Juin 2016 19:47:23
>
> > > Objet: Re: A new helper method Arrays.asArray
>
> > >
>
> > > Why would you not just write new Object[] {sort0, sort1, sort2, sort3}?
>
> > >
>
> > > On Tue, Jun 14, 2016, 10:35 AM <timo.kinnunen at gmail.com> wrote:
>
> > >
>
> > > >
>
> > > > Hi,
>
> > > >
>
> > > > I have found that many times I need to write this simple helper method:
>
> > > >
>
> > > > public static @SafeVarargs <T> T[] asArray(T… ts) { return ts; }
>
> > > >
>
> > > >
>
> > > > I usually need this when I have several implementations I’m comparing
> > > > and
>
> > > > I want to change the code for observing one of them to observing two or
>
> > > > more of them in sequence. I feel that in this case switching from
> > > > operating
>
> > > > on one object to operating on an unknown List implementation (from
>
> > > > Arrays.asList) is a too drastic change when all I need is put a
> > > > for-loop
>
> > > > around some code and iterate.
>
> > > >
>
> > > > The code for which I have to write this method is often some variation
> > > > of
>
> > > > something like this:
>
> > > >
>
> > > > Comparator<Object> sort1 = (x, y) -> (Integer) x - (Integer) y;
>
> > > > Comparator<Object> sort0 = (x, y) -> (int) (Math.pow((Integer) x,
>
> > > > 2.0) - Math.pow((Integer) y, 2.0));
>
> > > >
>
> > > > // Have to use a helper method here
>
> > > > Comparator<Object>[] sorts = asArray(sort0, sort1, sort2, sort3);
>
> > > >
>
> > > >
>
> > > > Please consider and add this simple method to Arrays.
>
> > > >
>
> > > >
>
> > > >
>
> > > > --
>
> > > > Have a nice day,
>
> > > > Timo
>
> > > >
>
> > > > Sent from Mail for Windows 10
>
> > > >
>
> > > >
>
> > >
>
More information about the core-libs-dev
mailing list