- 浏览: 145217 次
- 性别:
- 来自: 上海
最新评论
-
漂泊一剑客:
②非数字如何处理 对于文档中只要出现某些文字,就提升权重,没有 ...
solr使用dismax的一些record -
onelee:
同感同感只不过是身处一个起点比较高的创业公司
小公司做项目经理一些难处 -
babydeed:
看了一下豆瓣 感觉人气不旺 呵呵
亚马逊与当当的简单评价 -
悲剧了:
cuichang 写道要推荐去豆瓣,送货快是京东。其他价格之类 ...
亚马逊与当当的简单评价 -
cuichang:
要推荐去豆瓣,送货快是京东。其他价格之类的没多少区别。
亚马逊与当当的简单评价
泛型理解上的一个问题
请帮忙解释下这个泛型问题,具体逻辑我都下在代码注释里面了
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
谢谢你的分析,我想问下:
System.out.println(arr1.get(1));这个没有强制转换(Integer)而
System.out.println((String)arr2.get(1));强制转化成了(String)具体原因能分析下吗?
不是加载到了内存后arr1和arr2的类字节码都相同吗?为什么会出现这个情况
这个应该是正解。。。。
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
也可以在 System.out.println()处按F3,
System.out.println(arr1.get(1)); 进入的是PrintStream.println(Object x)
System.out.println(arr2.get(1)); 进入的是PrintStream.println(String x)
这样看明白了么,泛型虽然是编译期时使用,但不是对运行期没有影响
很好理解了~~~
问一下,代码反编译是怎么用的?用什么工具?eclipse有对应的插件么?
这个仍然只是结果阿,为什么会这样还是没解决撒。。
楼主3个问题:
Q1.下面打印出来true,证明泛型只是编译器级别的一个东西,加载到内存还是一样的
System.out.println(arr1.getClass()==arr2.getClass());
因为java泛型是擦除的,泛型在编译时信息就掉了,编译器看到的类似ArrayList<Object>。所以这两个对象比较类相等。
Q2.那么可以用跳过编译器用反射直接加入不通类型的东西,测试打印出"dodo"字符串
arr1.add(55);
arr1.getClass().getMethod("add", Object.class).invoke(arr1, "dodo");
System.out.println(arr1.get(1));
Q1里面的说的泛型擦除,在这里就是一个证明。在代码中arr1是 ArrayList<Integer>类型,但是用反射去找的时候,编译器已经把泛型擦除了。所以他的类型是ArrayList<Object>。这也就是为什么只能找到add(Object o)而不是add(Integer i)这个方法的原因了。
之所以没出错,是因为反射是运行时进行的,类型检查是编译时的。这段代码已经跳过了编译时类型检查,在运行时把String插入了没有泛型的List arr1中。
Q3既然如此那么下面这个也应该能正确打印,但是报异常异常为: java.lang.ClassCastException
这个具体原因不知到,我估计只是在处理基本类型wrapper和正常对象时,类型检查不一样。如果加上getClass()都会报错。这个问题带高人来解答了。
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
也可以在 System.out.println()处按F3,
System.out.println(arr1.get(1)); 进入的是PrintStream.println(Object x)
System.out.println(arr2.get(1)); 进入的是PrintStream.println(String x)
这样看明白了么,泛型虽然是编译期时使用,但不是对运行期没有影响
很好理解了~~~
问一下,代码反编译是怎么用的?用什么工具?eclipse有对应的插件么?
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
也可以在 System.out.println()处按F3,
System.out.println(arr1.get(1)); 进入的是PrintStream.println(Object x)
System.out.println(arr2.get(1)); 进入的是PrintStream.println(String x)
这样看明白了么,泛型虽然是编译期时使用,但不是对运行期没有影响
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
那为什么arr1没问题?
但是不管泛型指定为何种类型,他们加载到内存中的时候都是一种类型,我的帖子中arr1.getClass()==arr2.getClass()测试了这个,所以在通过编译器后他们在内存中操作都是当做一个对象来对待的,number下面的类型也会自动装箱.
不是这个问题,第一个元素和第二个元素加的都是一样的,我的意思是可以通过反射这种方式加入另外一种类型,比如你定义的泛型为OO,那么arr3.getClass().getMethod("add", Object.class).invoke(arr3, "why");
加入String类型的一个对象.
你取值时候会不会报异常呢?
我的代码是说:定义int型的泛型容器通过反射加入String类型的对象,然后get它,没问题
但是如果定义String型的泛型,通过反射加入int型的对象,就有问题了,报转换异常.....
public class Test01 { public static void main(String[] args) throws Exception{ ArrayList<Integer> arr1=new ArrayList<Integer>(); ArrayList<String> arr2=new ArrayList<String>(); //下面打印出来true,证明泛型只是编译器级别的一个东西,加载到内存还是一样的 System.out.println(arr1.getClass()==arr2.getClass()); //那么可以用跳过编译器用反射直接加入不通类型的东西,测试打印出"dodo"字符串 arr1.add(55); arr1.getClass().getMethod("add", Object.class).invoke(arr1, "dodo"); System.out.println(arr1.get(1)); //既然如此那么下面这个也应该能正确打印,但是报异常异常为: java.lang.ClassCastException arr2.add("why"); arr2.getClass().getMethod("add", Object.class).invoke(arr2, 33); System.out.println(arr2.get(1)); } }
评论
18 楼
悲剧了
2010-11-08
kala888 写道
悲剧了 写道
请帮忙解释下这个泛型问题,具体逻辑我都下在代码注释里面了
public class Test01 { public static void main(String[] args) throws Exception{ ArrayList<Integer> arr1=new ArrayList<Integer>(); ArrayList<String> arr2=new ArrayList<String>(); //下面打印出来true,证明泛型只是编译器级别的一个东西,加载到内存还是一样的 System.out.println(arr1.getClass()==arr2.getClass()); //那么可以用跳过编译器用反射直接加入不通类型的东西,测试打印出"dodo"字符串 arr1.add(55); arr1.getClass().getMethod("add", Object.class).invoke(arr1, "dodo"); System.out.println(arr1.get(1)); //既然如此那么下面这个也应该能正确打印,但是报异常异常为: java.lang.ClassCastException arr2.add("why"); arr2.getClass().getMethod("add", Object.class).invoke(arr2, 33); System.out.println(arr2.get(1)); } }
// Decompiled by DJ v3.6.6.79 Copyright 2004 Atanas Neshkov Date: 2010-11-08 9:27:39 // Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version! // Decompiler options: packimports(3) // Source File Name: Test.java package com.paic; import java.io.PrintStream; import java.lang.reflect.Method; import java.util.ArrayList; public class Test { public Test() { } public static void main(String args[]) throws Exception { ArrayList arr1 = new ArrayList(); ArrayList arr2 = new ArrayList(); System.out.println(arr1.getClass() == arr2.getClass()); arr1.add(Integer.valueOf(55)); arr1.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr1, new Object[] { "dodo" }); System.out.println(arr1.get(1)); arr2.add("why"); arr2.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr2, new Object[] { Integer.valueOf(33) }); System.out.println((String)arr2.get(1)); } }
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
谢谢你的分析,我想问下:
System.out.println(arr1.get(1));这个没有强制转换(Integer)而
System.out.println((String)arr2.get(1));强制转化成了(String)具体原因能分析下吗?
不是加载到了内存后arr1和arr2的类字节码都相同吗?为什么会出现这个情况
17 楼
forestking
2010-11-08
francis.xjl 写道
下面是我的猜想,仅供参考
再看了一下,我觉得应该是编译器进行了优化,跳过了一些步骤。
我们来读ArrayList的源码,它的add跟get方法是这样的:
因此,你如果在ArrayList<String>运行时插入一个Integer类型的数据,由于范型只存在编译期的缘故,而且add方法没有对类型进行检查,因此,可以成功。但是,当你想取出这个对象时,就有一个问题:get方法中有一个强制转换,按照道理是会抛出异常的,如果在你原来的程序中加入这么一句试一下就知道了:
因此,其实抛出异常是正常的。
那为什么直接输出arr1.get(1)就可以呢?我估计是这样的:我们知道打印一个对象其实就是调用这个对象的toString()方法,而toString()方法是Object类型中的,因此,可能编译器觉得这里的强制转换没有必要,因此给省略了这个步骤。
因此,我觉得String类型的ArrayList会抛出异常可能是编译器考虑到其它的一些原因而没有进行优化。
当然,这仅仅是我的猜想,仅供参考
再看了一下,我觉得应该是编译器进行了优化,跳过了一些步骤。
我们来读ArrayList的源码,它的add跟get方法是这样的:
public boolean add(E e) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public E get(int index) { RangeCheck(index); return (E) elementData[index]; }
因此,你如果在ArrayList<String>运行时插入一个Integer类型的数据,由于范型只存在编译期的缘故,而且add方法没有对类型进行检查,因此,可以成功。但是,当你想取出这个对象时,就有一个问题:get方法中有一个强制转换,按照道理是会抛出异常的,如果在你原来的程序中加入这么一句试一下就知道了:
// add by francis.xjl System.out.println(arr1.get(1).getClass());
因此,其实抛出异常是正常的。
那为什么直接输出arr1.get(1)就可以呢?我估计是这样的:我们知道打印一个对象其实就是调用这个对象的toString()方法,而toString()方法是Object类型中的,因此,可能编译器觉得这里的强制转换没有必要,因此给省略了这个步骤。
因此,我觉得String类型的ArrayList会抛出异常可能是编译器考虑到其它的一些原因而没有进行优化。
当然,这仅仅是我的猜想,仅供参考
这个应该是正解。。。。
16 楼
luobin23628
2010-11-08
利用thinking in java里的说法。。。
java里的泛型使用的是擦除机制。。 编译过后的类文件的泛型信息 已经被擦出了。。。 也就是说泛型只在编译期才存在。
因此 会有 arr1.getClass()==arr2.getClass()) 在运行期 arr1和arr2都ArrayList类型的
java里的泛型使用的是擦除机制。。 编译过后的类文件的泛型信息 已经被擦出了。。。 也就是说泛型只在编译期才存在。
因此 会有 arr1.getClass()==arr2.getClass()) 在运行期 arr1和arr2都ArrayList类型的
15 楼
pengliren
2010-11-08
泛型只是在编译的时候类型检测,你可以用反射添加测试测试
14 楼
Kensai
2010-11-08
francis.xjl 写道
bill.end 写道
kala888 写道
悲剧了 写道
请帮忙解释下这个泛型问题,具体逻辑我都下在代码注释里面了
public class Test01 { public static void main(String[] args) throws Exception{ ArrayList<Integer> arr1=new ArrayList<Integer>(); ArrayList<String> arr2=new ArrayList<String>(); //下面打印出来true,证明泛型只是编译器级别的一个东西,加载到内存还是一样的 System.out.println(arr1.getClass()==arr2.getClass()); //那么可以用跳过编译器用反射直接加入不通类型的东西,测试打印出"dodo"字符串 arr1.add(55); arr1.getClass().getMethod("add", Object.class).invoke(arr1, "dodo"); System.out.println(arr1.get(1)); //既然如此那么下面这个也应该能正确打印,但是报异常异常为: java.lang.ClassCastException arr2.add("why"); arr2.getClass().getMethod("add", Object.class).invoke(arr2, 33); System.out.println(arr2.get(1)); } }
// Decompiled by DJ v3.6.6.79 Copyright 2004 Atanas Neshkov Date: 2010-11-08 9:27:39 // Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version! // Decompiler options: packimports(3) // Source File Name: Test.java package com.paic; import java.io.PrintStream; import java.lang.reflect.Method; import java.util.ArrayList; public class Test { public Test() { } public static void main(String args[]) throws Exception { ArrayList arr1 = new ArrayList(); ArrayList arr2 = new ArrayList(); System.out.println(arr1.getClass() == arr2.getClass()); arr1.add(Integer.valueOf(55)); arr1.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr1, new Object[] { "dodo" }); System.out.println(arr1.get(1)); arr2.add("why"); arr2.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr2, new Object[] { Integer.valueOf(33) }); System.out.println((String)arr2.get(1)); } }
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
也可以在 System.out.println()处按F3,
System.out.println(arr1.get(1)); 进入的是PrintStream.println(Object x)
System.out.println(arr2.get(1)); 进入的是PrintStream.println(String x)
这样看明白了么,泛型虽然是编译期时使用,但不是对运行期没有影响
很好理解了~~~
问一下,代码反编译是怎么用的?用什么工具?eclipse有对应的插件么?
这个仍然只是结果阿,为什么会这样还是没解决撒。。
13 楼
Kensai
2010-11-08
楼主3个问题:
Q1.下面打印出来true,证明泛型只是编译器级别的一个东西,加载到内存还是一样的
System.out.println(arr1.getClass()==arr2.getClass());
因为java泛型是擦除的,泛型在编译时信息就掉了,编译器看到的类似ArrayList<Object>。所以这两个对象比较类相等。
Q2.那么可以用跳过编译器用反射直接加入不通类型的东西,测试打印出"dodo"字符串
arr1.add(55);
arr1.getClass().getMethod("add", Object.class).invoke(arr1, "dodo");
System.out.println(arr1.get(1));
Q1里面的说的泛型擦除,在这里就是一个证明。在代码中arr1是 ArrayList<Integer>类型,但是用反射去找的时候,编译器已经把泛型擦除了。所以他的类型是ArrayList<Object>。这也就是为什么只能找到add(Object o)而不是add(Integer i)这个方法的原因了。
之所以没出错,是因为反射是运行时进行的,类型检查是编译时的。这段代码已经跳过了编译时类型检查,在运行时把String插入了没有泛型的List arr1中。
Q3既然如此那么下面这个也应该能正确打印,但是报异常异常为: java.lang.ClassCastException
这个具体原因不知到,我估计只是在处理基本类型wrapper和正常对象时,类型检查不一样。如果加上getClass()都会报错。这个问题带高人来解答了。
12 楼
francis.xjl
2010-11-08
bill.end 写道
kala888 写道
悲剧了 写道
请帮忙解释下这个泛型问题,具体逻辑我都下在代码注释里面了
public class Test01 { public static void main(String[] args) throws Exception{ ArrayList<Integer> arr1=new ArrayList<Integer>(); ArrayList<String> arr2=new ArrayList<String>(); //下面打印出来true,证明泛型只是编译器级别的一个东西,加载到内存还是一样的 System.out.println(arr1.getClass()==arr2.getClass()); //那么可以用跳过编译器用反射直接加入不通类型的东西,测试打印出"dodo"字符串 arr1.add(55); arr1.getClass().getMethod("add", Object.class).invoke(arr1, "dodo"); System.out.println(arr1.get(1)); //既然如此那么下面这个也应该能正确打印,但是报异常异常为: java.lang.ClassCastException arr2.add("why"); arr2.getClass().getMethod("add", Object.class).invoke(arr2, 33); System.out.println(arr2.get(1)); } }
// Decompiled by DJ v3.6.6.79 Copyright 2004 Atanas Neshkov Date: 2010-11-08 9:27:39 // Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version! // Decompiler options: packimports(3) // Source File Name: Test.java package com.paic; import java.io.PrintStream; import java.lang.reflect.Method; import java.util.ArrayList; public class Test { public Test() { } public static void main(String args[]) throws Exception { ArrayList arr1 = new ArrayList(); ArrayList arr2 = new ArrayList(); System.out.println(arr1.getClass() == arr2.getClass()); arr1.add(Integer.valueOf(55)); arr1.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr1, new Object[] { "dodo" }); System.out.println(arr1.get(1)); arr2.add("why"); arr2.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr2, new Object[] { Integer.valueOf(33) }); System.out.println((String)arr2.get(1)); } }
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
也可以在 System.out.println()处按F3,
System.out.println(arr1.get(1)); 进入的是PrintStream.println(Object x)
System.out.println(arr2.get(1)); 进入的是PrintStream.println(String x)
这样看明白了么,泛型虽然是编译期时使用,但不是对运行期没有影响
很好理解了~~~
问一下,代码反编译是怎么用的?用什么工具?eclipse有对应的插件么?
11 楼
madbluesky
2010-11-08
编译器可以根据范型做优化的,答案楼上2位说的很清楚了。
将
将
ArrayList<String> arr2 = new ArrayList<String>();替换成
ArrayList<TestBean> arr2 = new ArrayList<TestBean>();将不会抛异常
10 楼
bill.end
2010-11-08
kala888 写道
悲剧了 写道
请帮忙解释下这个泛型问题,具体逻辑我都下在代码注释里面了
public class Test01 { public static void main(String[] args) throws Exception{ ArrayList<Integer> arr1=new ArrayList<Integer>(); ArrayList<String> arr2=new ArrayList<String>(); //下面打印出来true,证明泛型只是编译器级别的一个东西,加载到内存还是一样的 System.out.println(arr1.getClass()==arr2.getClass()); //那么可以用跳过编译器用反射直接加入不通类型的东西,测试打印出"dodo"字符串 arr1.add(55); arr1.getClass().getMethod("add", Object.class).invoke(arr1, "dodo"); System.out.println(arr1.get(1)); //既然如此那么下面这个也应该能正确打印,但是报异常异常为: java.lang.ClassCastException arr2.add("why"); arr2.getClass().getMethod("add", Object.class).invoke(arr2, 33); System.out.println(arr2.get(1)); } }
// Decompiled by DJ v3.6.6.79 Copyright 2004 Atanas Neshkov Date: 2010-11-08 9:27:39 // Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version! // Decompiler options: packimports(3) // Source File Name: Test.java package com.paic; import java.io.PrintStream; import java.lang.reflect.Method; import java.util.ArrayList; public class Test { public Test() { } public static void main(String args[]) throws Exception { ArrayList arr1 = new ArrayList(); ArrayList arr2 = new ArrayList(); System.out.println(arr1.getClass() == arr2.getClass()); arr1.add(Integer.valueOf(55)); arr1.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr1, new Object[] { "dodo" }); System.out.println(arr1.get(1)); arr2.add("why"); arr2.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr2, new Object[] { Integer.valueOf(33) }); System.out.println((String)arr2.get(1)); } }
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
也可以在 System.out.println()处按F3,
System.out.println(arr1.get(1)); 进入的是PrintStream.println(Object x)
System.out.println(arr2.get(1)); 进入的是PrintStream.println(String x)
这样看明白了么,泛型虽然是编译期时使用,但不是对运行期没有影响
9 楼
kala888
2010-11-08
悲剧了 写道
请帮忙解释下这个泛型问题,具体逻辑我都下在代码注释里面了
public class Test01 { public static void main(String[] args) throws Exception{ ArrayList<Integer> arr1=new ArrayList<Integer>(); ArrayList<String> arr2=new ArrayList<String>(); //下面打印出来true,证明泛型只是编译器级别的一个东西,加载到内存还是一样的 System.out.println(arr1.getClass()==arr2.getClass()); //那么可以用跳过编译器用反射直接加入不通类型的东西,测试打印出"dodo"字符串 arr1.add(55); arr1.getClass().getMethod("add", Object.class).invoke(arr1, "dodo"); System.out.println(arr1.get(1)); //既然如此那么下面这个也应该能正确打印,但是报异常异常为: java.lang.ClassCastException arr2.add("why"); arr2.getClass().getMethod("add", Object.class).invoke(arr2, 33); System.out.println(arr2.get(1)); } }
// Decompiled by DJ v3.6.6.79 Copyright 2004 Atanas Neshkov Date: 2010-11-08 9:27:39 // Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version! // Decompiler options: packimports(3) // Source File Name: Test.java package com.paic; import java.io.PrintStream; import java.lang.reflect.Method; import java.util.ArrayList; public class Test { public Test() { } public static void main(String args[]) throws Exception { ArrayList arr1 = new ArrayList(); ArrayList arr2 = new ArrayList(); System.out.println(arr1.getClass() == arr2.getClass()); arr1.add(Integer.valueOf(55)); arr1.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr1, new Object[] { "dodo" }); System.out.println(arr1.get(1)); arr2.add("why"); arr2.getClass().getMethod("add", new Class[] { java/lang/Object }).invoke(arr2, new Object[] { Integer.valueOf(33) }); System.out.println((String)arr2.get(1)); } }
这个是你的代码反编译以后的代码。。。然后你的注释,就都得到解答了。。。
8 楼
godtiger
2010-11-08
你假如的是基本类型 而不是封装类
7 楼
fishescape
2010-11-08
qianhd 写道
你们的瞎猜真没创意
改成 ArrayList arr2=new ArrayList<String>();
就不会有异常
至于为什么 回去慢慢想
改成 ArrayList arr2=new ArrayList<String>();
就不会有异常
至于为什么 回去慢慢想
那为什么arr1没问题?
6 楼
qianhd
2010-11-08
你们的瞎猜真没创意
改成 ArrayList arr2=new ArrayList<String>();
就不会有异常
至于为什么 回去慢慢想
改成 ArrayList arr2=new ArrayList<String>();
就不会有异常
至于为什么 回去慢慢想
5 楼
francis.xjl
2010-11-08
下面是我的猜想,仅供参考
再看了一下,我觉得应该是编译器进行了优化,跳过了一些步骤。
我们来读ArrayList的源码,它的add跟get方法是这样的:
因此,你如果在ArrayList<String>运行时插入一个Integer类型的数据,由于范型只存在编译期的缘故,而且add方法没有对类型进行检查,因此,可以成功。但是,当你想取出这个对象时,就有一个问题:get方法中有一个强制转换,按照道理是会抛出异常的,如果在你原来的程序中加入这么一句试一下就知道了:
因此,其实抛出异常是正常的。
那为什么直接输出arr1.get(1)就可以呢?我估计是这样的:我们知道打印一个对象其实就是调用这个对象的toString()方法,而toString()方法是Object类型中的,因此,可能编译器觉得这里的强制转换没有必要,因此给省略了这个步骤。
因此,我觉得String类型的ArrayList会抛出异常可能是编译器考虑到其它的一些原因而没有进行优化。
当然,这仅仅是我的猜想,仅供参考
再看了一下,我觉得应该是编译器进行了优化,跳过了一些步骤。
我们来读ArrayList的源码,它的add跟get方法是这样的:
public boolean add(E e) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public E get(int index) { RangeCheck(index); return (E) elementData[index]; }
因此,你如果在ArrayList<String>运行时插入一个Integer类型的数据,由于范型只存在编译期的缘故,而且add方法没有对类型进行检查,因此,可以成功。但是,当你想取出这个对象时,就有一个问题:get方法中有一个强制转换,按照道理是会抛出异常的,如果在你原来的程序中加入这么一句试一下就知道了:
// add by francis.xjl System.out.println(arr1.get(1).getClass());
因此,其实抛出异常是正常的。
那为什么直接输出arr1.get(1)就可以呢?我估计是这样的:我们知道打印一个对象其实就是调用这个对象的toString()方法,而toString()方法是Object类型中的,因此,可能编译器觉得这里的强制转换没有必要,因此给省略了这个步骤。
因此,我觉得String类型的ArrayList会抛出异常可能是编译器考虑到其它的一些原因而没有进行优化。
当然,这仅仅是我的猜想,仅供参考
4 楼
悲剧了
2010-11-07
wangzh1118 写道
你可以定义其它number类型的加入String 都没有问题。可能原因就是string属于引用类型,内存地址保存到int或long类型数组就没问题,反过来自然不行
但是不管泛型指定为何种类型,他们加载到内存中的时候都是一种类型,我的帖子中arr1.getClass()==arr2.getClass()测试了这个,所以在通过编译器后他们在内存中操作都是当做一个对象来对待的,number下面的类型也会自动装箱.
3 楼
wangzh1118
2010-11-07
你可以定义其它number类型的加入String 都没有问题。可能原因就是string属于引用类型,内存地址保存到int或long类型数组就没问题,反过来自然不行
2 楼
悲剧了
2010-11-07
francis.xjl 写道
我试了一下,自定义的类型也是可以的:
我猜:有可能是编译器对String类型的ArrayList进行了优化??
public class OO { @Override public String toString() { return super.toString(); } public static void main(String[]args) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { ArrayList<OO> arr3 = new ArrayList<OO>(); arr3.add(new OO()); //arr3.getClass().getMethod("add", Object.class).invoke(arr3, "dodo"); //correct //arr3.getClass().getMethod("add", Object.class).invoke(arr3, 33); //correct arr3.getClass().getMethod("add", Object.class).invoke(arr3, new OO()); //correct System.out.println(arr3.get(1)); } }
我猜:有可能是编译器对String类型的ArrayList进行了优化??
不是这个问题,第一个元素和第二个元素加的都是一样的,我的意思是可以通过反射这种方式加入另外一种类型,比如你定义的泛型为OO,那么arr3.getClass().getMethod("add", Object.class).invoke(arr3, "why");
加入String类型的一个对象.
你取值时候会不会报异常呢?
我的代码是说:定义int型的泛型容器通过反射加入String类型的对象,然后get它,没问题
但是如果定义String型的泛型,通过反射加入int型的对象,就有问题了,报转换异常.....
1 楼
francis.xjl
2010-11-07
我试了一下,自定义的类型也是可以的:
我猜:有可能是编译器对String类型的ArrayList进行了优化??
public class OO { @Override public String toString() { return super.toString(); } public static void main(String[]args) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { ArrayList<OO> arr3 = new ArrayList<OO>(); arr3.add(new OO()); //arr3.getClass().getMethod("add", Object.class).invoke(arr3, "dodo"); //correct //arr3.getClass().getMethod("add", Object.class).invoke(arr3, 33); //correct arr3.getClass().getMethod("add", Object.class).invoke(arr3, new OO()); //correct System.out.println(arr3.get(1)); } }
我猜:有可能是编译器对String类型的ArrayList进行了优化??
相关推荐
泛型类是具有一个或多个类型参数的类。类型参数是在定义类时使用的占位符,实际的类型在创建类的实例时指定。例如,我们可以创建一个名为`GenericContainer<T>`的泛型类,其中`T`就是类型参数。这个类可以存储任何...
C#泛型是.NET框架中的一个强大特性,它允许我们创建可重用的类型,这些类型可以在多种数据类型上工作,而无需重复编写相同代码。泛型的主要目标是提高代码的类型安全性和性能,同时减少类型转换的需要。在本文中,...
为了理解JVM如何处理泛型,我们需要了解一个重要的概念:“类型擦除”(Type Erasure)。类型擦除是指编译器在编译过程中去除所有泛型信息的过程。这一过程使得JVM不必直接支持泛型,因为所有泛型信息在编译后都被...
当我们谈论“java带两个类型参数的泛型”时,这意味着我们正在处理一个泛型类或泛型方法,它们接受不止一个类型作为参数。这样的设计可以让我们在不同数据类型之间建立更复杂的关联,同时保持类型安全。 首先,让...
此外,文件名`Java.jpg`可能表示的是一个与这个泛型例子相关的图片,可能是一个截图或者示意图,用于帮助理解泛型的概念或者`MyFirstGeneric`类的结构和用法。在实际学习过程中,视觉辅助工具往往能够帮助我们更好地...
综上所述,理解和熟练运用C#中的泛型集合对于任何C#初学者来说都是至关重要的。通过掌握List、Dictionary, TValue>等泛型集合的使用,以及类型约束和泛型接口的概念,开发者能够编写出更安全、高效且易于维护的代码...
这个声明定义了一个泛型类 List,其中 T 是一个类型参数。这个泛型类可以实例化为不同的类型,例如 List、List<string> 等。 2. 类型参数 类型参数是一个简单的标识符,它指示了用来创建一个构造类型的类型参数的...
Java泛型是Java编程语言中的一个重要特性,它允许在类、接口和方法中使用类型参数,从而提高了代码的类型安全性和可复用性。本文旨在深入解析Java泛型的各个方面,帮助开发者形成全面、清晰的理解。 1. **泛型基础*...
泛型是C#编程语言中的一个重要特性,自C# 2.0版本开始引入,它极大地提升了代码的重用性和效率。本专题将深入探讨泛型的原理和优势,以及如何利用它们来优化代码。 首先,泛型允许我们在定义类、接口、委托和结构时...
例如,可以定义一个泛型方法,使其能接受不同类型的参数并返回不同类型的值。 9. **类型推断** - 自JDK 7起,Java引入了类型推断,允许在某些情况下省略类型参数,编译器会根据上下文自动推断类型。 理解并熟练...
泛型类允许我们在定义类时指定一个或多个类型参数。例如,我们可以定义一个简单的泛型类 `Box`: ```java public class Box<T> { private T item; public void setItem(T item) { this.item = item; } public...
例如,`List<T>`就是一个泛型类,其中`T`代表一个未指定的类型,实际使用时可以是整型、字符串或其他自定义类型。 当我们想要在泛型中实现枚举功能时,可能的场景是在一个集合中存储一组特定类型的枚举值。例如,...
这个"3个泛型项目源码.rar"压缩包包含的三个项目,无疑为学习和理解泛型在实际项目中的应用提供了宝贵的资源。 泛型是C# 2.0引入的新特性,它允许开发者创建可以操作多种数据类型的类、接口和方法。这样做的好处...
泛型是Java编程语言中的一个重要特性,它引入了类型安全的概念,使得在编译时就能检查类型错误,而不是等到运行时。在类和方法上使用泛型,可以增强代码的可读性和复用性,避免类型转换的繁琐,并且提高了程序的效率...
例如,如果一个泛型类声明了类型参数`T extends Comparable<T>`,那么`T`必须是一个实现了`Comparable`接口的类型。这确保了使用该泛型类时,其内部操作能够正确地进行比较和排序。 自定义泛型类或算法时,开发者...
泛型编程的核心思想是参数化类型,即将数据类型作为一个参数传递给代码,使得代码能够适应不同类型的输入。 C++/CLI支持两种泛型机制:编译时泛型(基于ISO-C++模板)和运行时泛型(基于CLI泛型)。编译时泛型类似...
在C#编程中,泛型是一种强大的特性,它允许我们创建可重用的类型安全的代码,能够处理多种数据类型。"泛型封装.rar"这个...通过深入研究这个例子,开发者可以更好地理解和掌握C#中的泛型技术,提升代码质量和效率。