Effective Java 2nd Edition, Chapter 7, Item 42
Be careful when using var args. Do not abuse var args in our custmoized methods.
1) Painful Arrays.asList for Primitive Types
class="java" name="code">package edu.xmu.guava.constant; import static org.junit.Assert.assertEquals; import java.util.Arrays; import java.util.List; import org.junit.Test; import com.google.common.collect.Lists; import com.google.common.primitives.Ints; public class VarArgsTest { @Test public void varArgsTest() { int[] array = new int[] { 1, 2, 3, 4, 5 }; List<int[]> list = Arrays.asList(array); assertEquals(1, list.size()); list = Lists.newArrayList(array); assertEquals(1, list.size()); } @Test public void varArgsTest2() { String[] array = new String[] { "1", "2", "3", "4", "5" }; List<String> list = Arrays.asList(array); assertEquals(5, list.size()); list = Lists.newArrayList(array); assertEquals(5, list.size()); } @Test public void varArgsTest3() { int[] array = new int[] { 1, 2, 3, 4, 5 }; List<Integer> list = Ints.asList(array); assertEquals(5, list.size()); } }
? ?1> The reason why Arrays.asList returns List<int[]> instead of List<Integer> is that:
? ? ? ? 1> Before JDK 1.4, Arrays.asList(new int[]{1, 2, 3, 4, 5}); will produce a compilation error:
asList(Object[]) in Arrays can't be applied to (int[])
? ? ? ? ? ? ?This is because the signature of Arrays.asList is:
public static <T> List<T> asList(T[] a);
? ? ? ? ? ? ?And our passed in array is not an Object[] array.
? ? ? ? 2> But for JDK 1.5 or above, Arrays.asList supports var args, and the signature becomes:
public static <T> List<T> asList(T... a);
? ? ? ? ? ? ?And our passed in array, instead of its contents, is considered as the first element in var args.
? ? ? ? ? ? ?Thus, the asList(int[]{...}) returns List<int[]>
? ? 2> How can we safely handle this?
? ? ? ? ?Use Ints.asList(int... backingArray) in guava.
? ? ? ? ?And guava provides handful asList implementation for every primitive types:
? ? ? ? ?1) Booleans.asList
? ? ? ? ?2) Bytes.asList
? ? ? ? ?3) Shorts.asList
? ? ? ? ?4) Ints.asList
? ? ? ? ?5) Longs.asList
? ? ? ? ?6) Floats.asList
? ? ? ? ?7) Doubles.asList
? ? ? ? ?8) Chars.asList
2) Performance Penalty
? ? 1> Everytime we invoke the method who accepts var args will cause a relocation and initiation of an array.
@Test public void varArgsTest4() { String[] returnedStrs = dummyMethod("A", "B", "C"); String[] returnedStrs2 = dummyMethod("A", "B", "C"); String[] returnedStrs3 = dummyMethod("A", "B", "C"); assertNotEquals(returnedStrs, returnedStrs2); assertNotEquals(returnedStrs, returnedStrs3); } private String[] dummyMethod(String... strs) { return strs; }
? ? ? ?We can find out in example above that everytime we invoke the same dummyMethod, a totally new String[] will be returned.
? ? ? ?And it will affect our code's performance unintentionally.
? ? 2> How can we avoid this performance penalty and at the same time have the flexibility of var args.
? ? ? ?If we are pretty sure that this method will be invoked within 3 params at 95% confidence level, then we can make changes below to avoid performance penalty.
private void dummyMethod() { } private void dummyMethod(String var1) { } private void dummyMethod(String var1, String var2) { } private void dummyMethod(String var1, String var2, String var3) { } private void dummyMethod(String var1, String var2, String var3, String... rest) { }
?
Reference Links:
1)?https://stackoverflow.com/questions/2607289/converting-array-to-list-in-java/2607327#2607327
2)?http://stackoverflow.com/questions/1073919/how-to-convert-int-into-listinteger-in-java