java的List的原理以及使用
一,java的List的原理以及使用
1》Java的泛型是伪泛型。在编译期间,所有的泛型信息都会被擦除掉。正确理解泛型概念的首要前提是理解类型擦出(type erasure)。
2》Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。
3》如在代码中定义的List<object>和List<String>等类型,在编译后都会编程List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。类型擦除也是Java的泛型实现方法与C++模版机制实现方式(后面介绍)之间的重要区别。
4》原始类型(raw type)就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型。无论何时定义一个泛型类型,相应的原始类型都会被自动地提供。类型变量被擦除(crased),并使用其限定类型(无限定的变量用Object)替换
二,我们用代码解释下
1》Java的List的默认类型
List list = new ArrayList(); list.add(1); list.add("1"); list.add(1.236);
这个编译是不报错的,所以可得默认类型是object
2》Java为什么是伪泛型
List<Integer> list = new ArrayList<>(); //使用反射获取list的add方法 Method method = list.getClass().getMethod("add", Object.class); //如果使用Integer去反射获取方法是提示找不到的(错误提示:java.util.ArrayList.add(java.lang.Integer)),证明在编译后的类型是object //Method method = list.getClass().getMethod("add", Integer.class); //将这个字符串添加进入list集合中,而反射可以在Integer中加入String类型的值,所以也证明类型是object method.invoke(list, "Java反射机制实例。"); //打印出list中的数据,只有一条,因为我们只添加了一条 System.out.println(list.get(0));
错误如下图,代码
Method method = list.getClass().getMethod("add", Integer.class);
图
三,泛型的高级用法
abstract class TestAbstract<T> { public T say(T t) { return t; } public abstract T testOne(); public T testTwo(T t) { return t; } } class TestOne extends TestAbstract<String> { @Override public String testOne() { return "testOne"; } public String testTwo() { return super.testTwo("testTwo"); } }
使用
TestOne test = new TestOne(); String d = test.say("333"); String d1 = test.testOne(); String d2 = test.testTwo();