锁定老帖子 主题:关于JAVA 5可变参数
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (2)
|
|
---|---|
作者 | 正文 |
发表时间:2011-12-15
最后修改:2011-12-15
最近在用Arrays的asList()生成的List时,List元素的个数时而不正确。
//经多次测试,只要传递的基本类型的数组,生成List的元素个数均为1 char arrc = {'a','b'}; int arrint = {1,2,4}; Arrays.asList(arrc).size() ;// 结果为1; Arrays.asList(arrint ).size() ;//结果为1; //传递对象数组,元素个数正确。 String arrstr = {"a","b","java","spring","hadoop","lucene"}; Arrays.asList(arrstr ).size() ;//结果为6;
跟源码:
public static <T> List<T> asList(T... a) { return new ArrayList<T>(a); } 继续跟,Arrays的私有内部类ArrayList (没搞明白,为什么这里也起名为ArrayList)
private final E[] a; ArrayList(E[] array) { if (array==null) throw new NullPointerException(); a = array; } public int size() { return a.length; }
发现问题出在java5 的可变参数上。于是写了demo,测试。
public class TestArray { PrintStream out = System.out; @Test public void array() { char[] arrc = {'a','b','c','d','e'}; out.println("传递char数组:"); print(arrc); out.println("直接传递:"); print('a','b','c','d','e'); out.println("----------------------------"); int[] arri = {1,2,3,4,5,6,7}; out.println("传递int数组:"); print(arri); out.println("直接传递:"); print(1,2,3,4,5,6,7); out.println("----------------------------"); Integer[] arrInt = {1,2,3,4,5,6,7}; out.println("传递Integer数组:"); print(arrInt); out.println("直接传递:"); print(1,2,3,4,5,6,7); out.println("----------------------------"); String[] arrs = {"a","b","c","d","e"}; out.println("传递String数组:"); print(arrs); out.println("直接传递:"); print('a','b','c','d','e'); out.println("----------------------------"); } public void print(Object...arr){ out.print("内容:"+Arrays.toString(arr)); out.println("\t\t数组长度:"+arr.length+" "); } } 输出结果为: 传递char数组: 内容:[[C@defa1a] 数组长度:1 直接传递: 内容:[a, b, c, d, e] 数组长度:5 ---------------------------- 传递int数组: 内容:[[I@f5da06] 数组长度:1 直接传递: 内容:[1, 2, 3, 4, 5, 6, 7] 数组长度:7 ---------------------------- 传递Integer数组: 内容:[1, 2, 3, 4, 5, 6, 7] 数组长度:7 直接传递: 内容:[1, 2, 3, 4, 5, 6, 7] 数组长度:7 ---------------------------- 传递String数组: 内容:[a, b, c, d, e] 数组长度:5 直接传递: 内容:[a, b, c, d, e] 数组长度:5 ---------------------------- java 5 可变参数,直接传递值与传递数组处理的机制不太相同。
如果直接传递数组,基本类型数组将被视为一个对象而不会被解析成数组,如果直接传递参数将能正常解析。因此传递基本类型数组时强烈建议转为其封装类对象的数组 int ->Integer ,long->Long …………。(未对其封装) 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-12-15
最后修改:2011-12-15
public static <T> List<T> asList(T... a) {
return new ArrayList<T>(a); } 说明T只可能是对象,若不是对象像基本类型可能会存在装箱的操作,看了你的测试我发现,对于基本类型的数组,java似乎不会进行自动装箱操作 1.传递char[] arrc = {'a','b'} Arrays.asList(arrc) 1 估计是把数组作一个对象直接传递过 2.传递 char a ='a',char b='b' Arrays.asList(a,b) 2 装箱后的传递 不知道对不对(可能自己表达能力有限) |
|
返回顶楼 | |
发表时间:2011-12-19
toArray() 这个函数必须只能传对象,就能看出来了
|
|
返回顶楼 | |
发表时间:2011-12-19
最后修改:2011-12-19
这样写就很清楚了吧
public static void main(String[] args) { int[] intArray = {1,2,3}; List<int[]> myList = Arrays.asList(intArray); System.out.println(myList.size()); System.out.println(myList.get(0).length); } 数组被作为一个参数传递到函数中,而不是扩展为变参。楼主说到的对象类型数组确实效果不同,同求解释。 大概明白了:定义: public static <T> List<T> asList(T... a) { return new ArrayList<T>(a); }这个T必须是对象类型。好比我们不能new ArrayList<int> 只能new ArrayList<Integer> |
|
返回顶楼 | |
发表时间:2011-12-20
最后修改:2011-12-20
public static <T> List<T> asList(T... a) { return new ArrayList<T>(a); } 如果是基本类型数组,自动装箱将数组包装为对象如 int[] intArray = new int[] { 1, 2}; T... a 就是 [[1, 2]],可以看到 a 的 size 将为 1 如果是对象数组,不需要自动装箱如 Integer[] integerArray = new Integer[] { 1, 2}; T... a 就是 [1, 2],可以看到 a 的 size 将为 2 |
|
返回顶楼 | |
发表时间:2011-12-23
其实只要记住这句话就ok了:
基本类型的一位数组可以被当作Object类型使用(1.5),不能当做Object[]类型使用(1.4);非基本类型的一维数组,既可以当做Object类型使用(1.5)也可以当做Object[]类型使用(1.4) jdk1.4 public static <T> List<T> asList(Object[] a) jdk1.5 public static <T> List<T> asList(T... a) 按jdk1.5的语法,整个数组是一个参数,而jdk1.4的语法,数组中额度每个元素对应一个参数。 javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按照jdk1.4的语法进行处理,即把数组打撒成为若干个单独的参数。当jdk1.4不能处理时交由jdk1.5处理。 出现楼主的现象其实就是jdk1.4能够处理的范围。 看下数组与Object的关系: int[] a1=new int[]{1,2,3}; int[] a2=new int[]{4}; int[][] a3=new int[2][3]; String [] a4=new String[]{"a","b","c"}; 1、代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。即他们都能被jdk1.5处理。 // getSuperclass // public Class<? super T> getSuperclass()返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的Class。如果此 Class 表示 Object 类、一个接口、一个基本类型或 void,则返回 null。如果此对象表示一个数组类,则返回表示该 Object 类的 Class 对象。 // 返回: // 此对象所表示的类的超类。 System.out.println(a1.getClass().getSuperclass().getName());//java.lang.Object System.out.println(a2.getClass().getSuperclass().getName());//java.lang.Object System.out.println(a3.getClass().getSuperclass().getName());//java.lang.Object System.out.println(a4.getClass().getSuperclass().getName());//java.lang.Object Object obj1=a1; Object obj2=a3; Object obj3=a3; Object obj4=a4; 2、基本类型的一位数组可以被当作Object类型使用(1.5),不能当做Object[]类型使用(1.4);非基本类型的一维数组,既可以当做Object类型使用(1.5)也可以当做Object[]类型使用(1.4) //Object[] objs1=a1;//int的不是Object //Object[] objs2=a2; Object[] objs3=a3;//int[]是个Object对象 Object[] objs4=a4;//字符串数组里的字符串是Object,即Object数组里的Object Object[] 与String[]没有父子关系,Object与String有父子关系,所以new Object[]{“aaa”,”bb”}不能强制转换成new String[]{“aaa”,”bb”};,Object x = “abc”能强制转换成String x = “abc”。 楼主测试代码修改下: import java.io.PrintStream; import java.lang.reflect.Array; import java.util.Arrays; import java.util.List; import org.junit.Test; public class TestArray { PrintStream out = System.out; @Test public void array() { char[] arrc = {'a','b','c','d','e'}; out.println("传递char数组:"); // print(arrc); //其实Object[] arr没有处理,他还是真正Object...arr处理的。所以你把print方法参数改为Object[] arr报错 printtt(arrc); printObject(arrc); out.println(); out.println("直接传递:"); printtt('a','b','c','d','e'); out.println("----------------------------"); int[] arri = {1,2,3,4,5,6,7}; out.println("传递int数组:"); //print(arri); //其实Object[] arr没有处理,他还是真正Object...arr处理的。所以你把print方法参数改为Object[] arr报错 printtt(arri); printObject(arri); out.println(); out.println("直接传递:"); printtt(1,2,3,4,5,6,7); out.println("----------------------------"); Integer[] arrInt = {1,2,3,4,5,6,7}; out.println("传递Integer数组:"); print(arrInt); //其实当作Object[] arr处理了 printtt(arrInt); printObject(arrInt); out.println(); out.println("直接传递:"); printtt(1,2,3,4,5,6,7); out.println("----------------------------"); String[] arrs = {"a","b","c","d","e"}; out.println("传递String数组:"); print(arrs); //其实当作Object[] arr处理了 printtt(arrs); printObject(arrs); out.println(); out.println("直接传递:"); printtt('a','b','c','d','e'); out.println("----------------------------"); } public void print(Object[] arr){ out.print("内容:"+Arrays.toString(arr)); // public static String toString(Object[] a) out.println("\t\t数组长度:"+arr.length+" "); } public void printtt(Object...arr){ out.print("内容:"+Arrays.asList(arr)); out.println("\t\t数组长度:"+arr.length+" "); // public static <T> List<T> asList(T... a) } //用Array工具类用于完成对数组的反射操作,可以决绝上面所产生的问题 public static void printObject(Object obj){ Class cla=obj.getClass(); if (cla.isArray()) { int len=Array.getLength(obj); for (int i = 0; i < len; i++) { System.out.print(Array.get(obj, i)); } } else { System.out.println(obj); } } } |
|
返回顶楼 | |
发表时间:2011-12-23
最后修改:2011-12-23
其实只要记住这句话就ok了: 基本类型的一位数组可以被当作Object类型使用(1.5),不能当做Object[]类型使用(1.4);非基本类型的一维数组,既可以当做Object类型使用(1.5)也可以当做Object[]类型使用(1.4)
jdk1.4 public static <T> List<T> asList(Object[] a) jdk1.5 public static <T> List<T> asList(T... a) 按jdk1.5的语法,整个数组是一个参数,而jdk1.4的语法,数组中额度每个元素对应一个参数。 javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按照jdk1.4的语法进行处理,即把数组打撒成为若干个单独的参数。当jdk1.4不能处理时交由jdk1.5处理。 出现楼主的现象其实就是jdk1.4能够处理的范围。 看下数组与Object的关系: int[] a1=new int[]{1,2,3}; int[] a2=new int[]{4}; int[][] a3=new int[2][3]; String [] a4=new String[]{"a","b","c"}; 1、代表数组的Class实例对象的getSuperClass()方法返回的父类为Object类对应的Class。即他们都能被jdk1.5处理。 // getSuperclass // public Class<? super T> getSuperclass()返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的Class。如果此 Class 表示 Object 类、一个接口、一个基本类型或 void,则返回 null。如果此对象表示一个数组类,则返回表示该 Object 类的 Class 对象。 // 返回: // 此对象所表示的类的超类。 System.out.println(a1.getClass().getSuperclass().getName());//java.lang.Object System.out.println(a2.getClass().getSuperclass().getName());//java.lang.Object System.out.println(a3.getClass().getSuperclass().getName());//java.lang.Object System.out.println(a4.getClass().getSuperclass().getName());//java.lang.Object Object obj1=a1; Object obj2=a3; Object obj3=a3; Object obj4=a4;
2、基本类型的一位数组可以被当作Object类型使用(1.5),不能当做Object[]类型使用(1.4);非基本类型的一维数组,既可以当做Object类型使用(1.5)也可以当做Object[]类型使用(1.4) //Object[] objs1=a1;//int的不是Object //Object[] objs2=a2; Object[] objs3=a3;//int[]是个Object对象 Object[] objs4=a4;//字符串数组里的字符串是Object,即Object数组里的Object Object[] 与String[]没有父子关系,Object与String有父子关系,所以new Object[]{“aaa”,”bb”}不能强制转换成new String[]{“aaa”,”bb”};,Object x = “abc”能强制转换成String x = “abc”。
楼主测试代码修改下:
import java.io.PrintStream; import java.lang.reflect.Array; import java.util.Arrays; import java.util.List; import org.junit.Test; public class TestArray { PrintStream out = System.out; @Test public void array() { char[] arrc = {'a','b','c','d','e'}; out.println("传递char数组:"); // print(arrc); //其实Object[] arr没有处理,他还是真正Object...arr处理的。所以你把print方法参数改为Object[] arr报错 printtt(arrc); printObject(arrc); out.println(); out.println("直接传递:"); printtt('a','b','c','d','e'); out.println("----------------------------"); int[] arri = {1,2,3,4,5,6,7}; out.println("传递int数组:"); //print(arri); //其实Object[] arr没有处理,他还是真正Object...arr处理的。所以你把print方法参数改为Object[] arr报错 printtt(arri); printObject(arri); out.println(); out.println("直接传递:"); printtt(1,2,3,4,5,6,7); out.println("----------------------------"); Integer[] arrInt = {1,2,3,4,5,6,7}; out.println("传递Integer数组:"); print(arrInt); //其实当作Object[] arr处理了 printtt(arrInt); printObject(arrInt); out.println(); out.println("直接传递:"); printtt(1,2,3,4,5,6,7); out.println("----------------------------"); String[] arrs = {"a","b","c","d","e"}; out.println("传递String数组:"); print(arrs); //其实当作Object[] arr处理了 printtt(arrs); printObject(arrs); out.println(); out.println("直接传递:"); printtt('a','b','c','d','e'); out.println("----------------------------"); } public void print(Object[] arr){ out.print("内容:"+Arrays.toString(arr)); // public static String toString(Object[] a) out.println("\t\t数组长度:"+arr.length+" "); } public void printtt(Object...arr){ out.print("内容:"+Arrays.asList(arr)); out.println("\t\t数组长度:"+arr.length+" "); // public static <T> List<T> asList(T... a) } //用Array工具类用于完成对数组的反射操作,可以决绝上面所产生的问题 public static void printObject(Object obj){ Class cla=obj.getClass(); if (cla.isArray()) { int len=Array.getLength(obj); for (int i = 0; i < len; i++) { System.out.print(Array.get(obj, i)); } } else { System.out.println(obj); } } }
|
|
返回顶楼 | |
发表时间:2011-12-23
分析的不错,楼上这个说的也挺好的
|
|
返回顶楼 | |
发表时间:2011-12-25
基本类型的一位数组可以被当作Object类型使用(1.5),不能当做Object[]类型使用(1.4);非基本类型的一维数组,既可以当做Object类型使用(1.5)也可以当做Object[]类型使用(1.4);
|
|
返回顶楼 | |
浏览 4956 次