一个朋友圈泛型问题引起的“案子”

昨天朋友圈问了一个问题:
对于下面的list,何如在list添加一个Integer型整数?java

ArrayList<String> list = new ArrayList<String>();复制代码

有这样几种回答:bash

  • 1.不知道(非专业回答)
  • 2.硬塞(非专业回答)
  • 3.把String 改为Integer再添加(违背了问题初衷)
  • 4.把String改为Object,能够加任意类型(违背了问题初衷)
  • 5.String换成通配符
  • 6.反射

对于一、2就不说了,属于搞事情的!三、四、5三种方式违背了问题的初衷,若是能够改,那咱们直接new三个ArrayList就能够了。6反射,这个是无限接近的,那么这个和反射有什么关系呢?下来看下下面几个例子:spa

public static void main(String[] args) {

        ArrayList list=new ArrayList();

        ArrayList<String> str_list=new ArrayList<String>();

        ArrayList<Integer> int_list=new ArrayList<Integer>();

        ArrayList<Object> obj_list=new ArrayList<Object>();
        //对象比较
        System.out.println(list == str_list);
        System.out.println(list == int_list);
        System.out.println(list == obj_list);

        //对象的运行时class比较
        System.out.println(list.getClass() == str_list.getClass());
        System.out.println(list.getClass() == int_list.getClass());
        System.out.println(list.getClass() == obj_list.getClass());
    }复制代码

结果:code

false
false
false
true
true
true复制代码

其实上面三个很容易理解,不一样对象在内存中的地址确定是不一样的,所以均为false;下面三个均为true?是的,确实为true,这就引出了朋友圈的那个问题。为何不一样的三个对象,他们的getClass是同样的,不该该是有三个不一样的hashCode吗?这个其实就是泛型编译时和运行时的问题
对于泛型来讲,泛型只在编译阶段有效,编译以后,集合的泛型是去泛型化的;缘由:因为JVM泛型的擦除机制,在运行时JVM是不知道泛型信息的
所以:java集合中的泛型,是来约束用户的错误输入的,只在编译时有效;
在回到问题最初,咱们怎么才能将一个Integer对像放入上面定义的list中呢?既然集合中的泛型是编译时有效的,那我咱们就能够经过绕过编译的方式进行插入。那么如何绕过编译时的校验呢?答案就是用反射;咱们知道JAVA反射机制是指:
“在运行状态中,对于任意一个类,都可以知道这个类的全部属性和方法;对于任意一个对象,都可以调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
OK,再来看程序:对象

ArrayList<String> str_list=new ArrayList<String>();
        //获取类信息
        Class c=str_list.getClass();
        //获取add方法
        Method m=c.getMethod("add", Object.class);
        //运行时调用add方法
        m.invoke(str_list, 20);
        //输出当前str_list
        System.out.println(str_list);复制代码

结果:内存

[20]复制代码

从结果能够看出,咱们完成了在list中添加Integer的任务。
【泛型、反射、编译时、运行时】
你们周末愉快!get

相关文章
相关标签/搜索