泛型就这么简单
为什么需要泛型
public class GenericTest {
public static void main(String[] args) {
List list = new ArrayList();
list.add("qqyumidi");
list.add("corn");
list.add(100);
for (int i = 0; i < list.size(); i++) {
String name = (String) list.get(i); // 1
System.out.println("name:" + name);
}
}
}
在如上的编码过程中,我们发现主要存在两个问题:
1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。
2.因此,// 1 处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常,是因为不能将int类型强制转换为String类型。
那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现“java.lang.ClassCastException”异常呢?
答案就是使用泛型。
什么是泛型
JDK1.5之后出现了新的技术——泛型(Generic),此技术的最大特点是类中的属性的类型可以由外部决定。 >>(使用者,因为开发者本身并不知道需要什么类型。)
public interface List<E> extends Collection<E>{ //E是元素的意思,只是一个含义,不知道真正代表哪个类型,由外部真正实例化时传进来
. . .
}
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?
顾名思义,就是将类型由原来的变成具体的类型,此时类型也定义成参数形式,然后在使用/调用时传入具体的类型。在写代码的时候不需要关心真正的类型是什么,在使用时才会去关心。
@Test public void test1(){
List<string>list = new ArrayList<String>() //<String>可以不写,也可以只写<>,也可以与前面的对应,写上具体的类型。
;list.add("vince");
list.add(10);//报错,因为上面参数化类型具体化了<String>
list.add(new object());//同样报错
for(inti=0;i<list.size();i++){
//如果我们不能确定集合中的元素类型,那么我们需要在处理元素时
//要判断元素的类型,才能做相应的操作
}
泛型类
定义类:*T:参数化类型,在实际使用时才会指定具体的类到
泛型只作用于编译期检查,在编译后,会被擦除
*/
public class Node<T>{
private T data;
public Node(){}
public Node(T data){
this.data=data;
}
public T getData(){
return data;
}
public void setData(T data){
this.data=data;
}
使用:
@Test
public void testNode(){
Node<String> stringNode = new Node<>("Jack");
Node<Integer> intNode = new Node<>(10);
System.out.printin(stringNode.getData());
System.out.printin(intNode.getData());
}
附:Java泛型中的标记符含义:
- ? 表示不确定类型,和Object类型不同
- E 一般表示Element,T 一般表示Type,K一般表示Key,V一般表示Value,不过这些可以混用,没有限制
- Object 则是包含所有类型
三种List的生命方法
List<?> list1;
List<E> list2;
List<Object> list3;
Object跟这些标记符代表的java类型有啥区别呢?
Object是所有类的根类,任何类的对象都可以设置给该Object引用变量,使用的时候可能需要类型强制转换,
但是用使用了泛型T、E等这些标识符后,在实际用之前类型就已经确定了,不需要再进行类型强制转换。
jdk中的K,V,T,E等泛型名称不是固定写法,这些名称是可以改的,比如改成zhangsan,lisi都可以