• java泛型


    为什么要用泛型?

    Java有个缺点:当我们把一个对象丢进集合中后,集合就会忘记这个对象的数据类型,把他们当成Object类处理,当再次取出这个对象时,需要强制转化数据类型。

    Java集合之所以被设计成这样,是因为集合的程序员不会知道我们需要用它来保存什么类型的对象,所以把他们设计成能保存任何类型的对象,只要求很好的通用性。但是存在两个问题:

    l 例如想创建一个只能保存Dog类型的集合,但是程序也可以添加Cat对象进去。

    l 给取出元素造成不必要的麻烦。

    使用泛型的好处:可以写出更加通用的代码,帮我们检查语法(泛型只在编译阶段有效)。

    在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

    • demo

    public class TestgenericList {
    public static void main(String[] args) {
    List<String> l=new ArrayList<String>();
    l.add("bob");
    l.add("张三");
    l.add("李四");
    //下面的代码将引起编译错误
    // l.add(5);
    for(String str:l){
    //无需强制转化
    String name=str;
    System.out.println(name);
    }
    }
    }

    定义泛型接口、泛型类

    • List接口

    public interfere List<E>
    {
     //在该接口中,E可以作为类型使用
     //下面方法可以使用E作为参数类型。
     void add(E e);
     Iterator<E> iterator();
    }

    不仅集合可以增加泛型,任何类都可以增加,虽然泛型是集合的重要场合。下面自定义了一个Apple类,这个类就可以包含一个泛型声明

    public class Apple<T> {
    private T info;
    public Apple(){}
    public Apple(T info){
    this.info=info;
    }
      ...
    }

     

    并不存在的泛型类

    • 直接看代码

    List<String> l1=new ArrayList<String>();
    List< Integer > l2=new ArrayList<Integer>();
    System.out.println(l1.getClass()==l2.getClass());   // ? true

    不可以这样判断:if(cs instanceof List<String>)

    通配符(表示各种泛型List的父类)

    问题:形参的类型需要使用通用类型。

    public void fun(Generic<Number> obj){}

    Generic<Integer> gInteger = new Generic<Integer>(123);
    fun(gInteger);

    这段代码会报错

    public void test( List<?> l ) { }
    // 不管List泛型是什么类型,都被当成了Object类处理

    通配符的上下限

    class Apple<T extends Number>{  // Number为T的上限,T不能是Number的父类,可以是Number类型
    public T info;
    public String toString(){
    return "info: "+this.info;
    }
    }
    class Apple<T super Number>{  // Number为T的下限
    public T info;
    public String toString(){
    return "info: "+this.info;
    }
    }

    泛型方法

    // T是方法的类型参数,可以根据实参的类型就行推断
    public static <T> void test(T[]a,Collection<T> c){
       for(T t:a){
           c.add(t);
      }
    }
    public static void main(String[] args) {
       Collection<Object> cl=new ArrayList<Object>();
       Object []obj=new Object[3];
       obj[0]="zhangsan";
       obj[1]="lisi";
       obj[2]="bob";
       test(obj,cl);   // 根据object的实际类型推断出T类型
       System.out.println(cl);
       //
       String []str={"A","B","C"};
       Collection<String> cl1=new ArrayList<String>();
       //这时以Collection为基准
       test(str,cl);
       System.out.println(cl);
    }

    先在public与返回值之间的<T>必不可少,这表明这是一个泛型方法

    也可以定义多个泛型参数:public static <T,S> void fun(){}

    限定上下限

    <T> void test(Collection<? extends T> a,Collection<T> c){}

     

    擦除和转换

    在做类型转换的时候,如果去掉了类型参数,则会造成对象的类型参数丢失,编译器认为类型参数为Object

    public static void main(String[] args) {
       Apple<Integer> a=new Apple<Integer>();
       //a的getSize方法返回一个Integer对象
       Integer in=a.getSize();
       //把a对象赋值给Apple对象,则会丢失尖括号的信息
       Apple a1=a;  
       //下面的代码将会导致编译错误
       // Integer in1=a1.getSize();
    }

     

  • 相关阅读:
    医院产品演变畅想
    2014-1-19
    更新一下blog
    tostring的自动调用
    解决evernote更新报错问题
    健身日记
    跑步计划
    [转载]offsetHeight , clientHeight, scrollHeight 区别
    做一个院友网站杂记
    查好友摇一摇功能的感受
  • 原文地址:https://www.cnblogs.com/zhuxiang1633/p/11249757.html
Copyright © 2020-2023  润新知