昨天朋友圈问了一个问题:
对于下面的list,何如在list添加一个Integer型整数?
1 | 复制代码ArrayList<String> list = new ArrayList<String>(); |
有这样几种回答:
- 1.不知道(非专业回答)
- 2.硬塞(非专业回答)
- 3.把String 改成Integer再添加(违背了问题初衷)
- 4.把String改成Object,可以加任意类型(违背了问题初衷)
- 5.String换成通配符
- 6.反射
对于1、2就不说了,属于搞事情的!3、4、5三种方式违背了问题的初衷,如果可以改,那我们直接new三个ArrayList就可以了。6反射,这个是无限接近的,那么这个和反射有什么关系呢?下来看下下面几个例子:
1 | 复制代码public static void main(String[] args) { |
结果:
1 | 复制代码false |
其实上面三个很容易理解,不同对象在内存中的地址肯定是不同的,因此均为false;下面三个均为true?是的,确实为true,这就引出了朋友圈的那个问题。为什么不同的三个对象,他们的getClass是一样的,不应该是有三个不同的hashCode吗?这个其实就是泛型编译时和运行时的问题。
对于泛型来说,泛型只在编译阶段有效,编译之后,集合的泛型是去泛型化的;原因:由于JVM泛型的擦除机制,在运行时JVM是不知道泛型信息的。
因此:java集合中的泛型,是来约束用户的错误输入的,只在编译时有效;
在回到问题最初,我们怎么才能将一个Integer对像放入上面定义的list中呢?既然集合中的泛型是编译时有效的,那我我们就可以通过绕过编译的方式进行插入。那么如何绕过编译时的校验呢?答案就是用反射;我们知道JAVA反射机制是指:
“在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
OK,再来看程序:
1 | 复制代码 ArrayList<String> str_list=new ArrayList<String>(); |
结果:
1 | 复制代码[20] |
从结果可以看出,我们完成了在list中添加Integer的任务。
【泛型、反射、编译时、运行时】
大家周末愉快!
本文转载自: 掘金