zoukankan      html  css  js  c++  java
  • 黑马程序员_<<泛型>>

    --------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------


    1.     泛型

         1.概述

               泛型是为了解决了集合中存储对象安全问题,如果集合中存数了不同类型的对象,那么读取出来后,操作取出的对象以为不知道类型,会出现安全问题,但是这不会在编译时期提示错误,而是会在运行时期出现问题,所以泛型会把运行时期的错误移到了编译时期,那么错误就会避免。

         2.集合中的泛型

               在集合中都会存在泛型,下同时迭代器中也定义了泛型,在读取出来后,我们也要指定迭代器的类型,这样我们就不需要强制类型转换了,因为迭代器中就指定了类型,所以读取出来的对象类型也就是我们指定的类型。

     

    package www.fuxi.jihe;
     
    import java.util.ArrayList;
    import java.util.Iterator;
     
    public class fanxingDemo {
       public static void main(String[] args) {
         ArrayList<String> list = new ArrayList<String>();
         list.add("zhangsan");// 在这里必须传入的String对象,如果不是那么编译会出错误
         list.add("lisi");
         Iterator<String>it = list.iterator();// 在这里也要指定迭代器的类型
         while (it.hasNext()) {
            String s = it.next();// 在这里不需要强制类型转换为String了,因为迭代器已经指定了类型
            System.out.println(s);
         }
       }
     
    }
    结果:
    zhangsan
    lisi


    2.     自定义泛型类

    自定义的泛型类,可以按照我们随意要求指定类型

     

    package www.fuxi.jihe;
     
    /**
     * 在此类型定义了一个泛型,这个字母可以随便定义当创建了此类的对象,那么就需要指定泛型的类型,那么里面的成员泛型就统一指定了
     */
    package www.fuxi.jihe;
     
    public class Demo<T> {
       private T t;
       public void set(T t){//此方法是和类上的泛型一起变化
         this.t=t;
         System.out.println("set:"+t);
       }
      
       public static void main(String [] agrs){
         Demo<String> d=new Demo<String>();
         d.set("123");
        
       }
     
    }
    结果:
    set:123


    3.     泛型方法

    1.     一个泛型

       

    public class Demo<T> {
     
       public void show(T t) {
         System.out.println("show:" + t);
       }
     
       public void print(T t) {
         System.out.println("print:" + t);
       }
     
       public static void main(String[] args) {
         Demo<String> d = new Demo<String>();
         d.show("hello");
         d.print("world");
         // d.show(new
         // Integer(2));//在这里编译出错,因为d对象泛型已经指定了是String类型,所以参数全部是String类型
         System.out.println("-----------");
         Demo<Integer> d1 = new Demo<Integer>();
         d1.show(new Integer(3));
         d1.print(new Integer(6));
       }
     
    }
    结果:
    show:hello
    print:world
    -----------
    show:3
    print:6

    2.     多个泛型

     

    package www.fuxi.jihe;
     
    public class Demo<T> {
       public void set(T t){//此方法是和类上的泛型一起变化
         System.out.println("set:"+t);
       }
       public <Q> void get(Q q){//此方法上的泛型是和类上的泛型无关,可以是任意类型
         System.out.println("get:"+q);
       }
       public static void main(String [] agrs){
         Demo<String> d=new Demo<String>();
         d.set("123");
         d.get("abc");
         d.get(5);
       }
     
    }
     
    结果:
    set:123
    get:abc
    get:5
     


    从结果可以看出,这个类中既有和类上的泛型一起变化的,也有自己特有的方法,例如:get()方法上的泛型,可以和类上的一样也可以不一样。

    3.静态方法上的泛型

      把泛型定义在返回值和修饰符之间

    静态方法上的泛型的定义需要自己定义,不要和类上的泛型统一,因为静态方法只要是类一加载就生成,如果和类上的泛型统一的话,在静态方法加载的时候,没有对象生成,也就没有指定泛型的类型,那么就会出错,这些都和泛型定义出现的时间有关。

     

    package www.fuxi.jihe;
     
    public class Demo<T> {
      
       public static <Q> void show(Q q){//这里不要和类上的泛型统一
         System.out.println("show:"+q);
       }
       public static void main(String [] agrs){
         Demo.show("hello");
        
       }
     
    }
    结果:
    show:hello


    4.     接口泛型

         在接口上自定义泛型

     

    package www.fuxi.jihe;
     
    interface inter<T> {
       void show(T t);
    }
     
    /* 第一种实现泛型接口,在接口上指定泛型类型 */
    public class Demo implements inter<String> {
       public void show(String t) {
         System.out.println("show:" + t);
       }
     
       public static void main(String[] agrs) {
         Demo d = new Demo();
         d.show("hellowrold");
       }
    }
    结果:
    show:hello world


    下面是在对象是上指定泛型类型

     

    package www.fuxi.jihe;
     
    interface inter<T> {
       void show(T t);
    }
     
    /* 第二种实现泛型接口,在接口上不定义泛型,而是在对象上指定泛型类型 */
    public class Demo<T> implements inter<T> {
       public void show(T t) {
         System.out.println("show:" + t);
       }
     
       public static void main(String[] agrs) {
         Demo<Integer> d = new Demo<Integer>();
         d.show(3);
       }
    }
     
    结果:
    show:3


    5.     泛型的高级应用

    1.     通配符

    通配符用?表示,也叫占位符,可以表示任意类型

     

    package www.fuxi.jihe;
     
    import java.util.ArrayList;
    import java.util.Iterator;
     
    public class Demo {
       /*在这里泛型类型使用通配符表示,表次是此可以传入任意类型*/
       public void show(ArrayList<?> list) {
         Iterator<?> it = list.iterator();
         while (it.hasNext()) {
            System.out.println(it.next());
         }
       }
     
       public static void main(String[] agrs) {
         Demo d = new Demo();
         ArrayList<String> l1 = new ArrayList<String>();
         l1.add("abc");
         l1.add("123");
         l1.add("ased");
         d.show(l1);
         System.out.println("---------");
         ArrayList<Integer> l2 = new ArrayList<Integer>();
         l2.add(1);
         l2.add(2);
         l2.add(3);
         d.show(l2);
       }
    }
    结果:
    abc
    123
    ased
    ---------
    1
    2
    3


    但是也可以使用另一中方式表示,但是其有缺点,不能表示一个范围类型,通配符可以表示一个类型范围,详细“2.参考通配符设置上下限”

     

    package www.fuxi.jihe;
     
    import java.util.ArrayList;
    import java.util.Iterator;
     
    public class Demo {
       /* 在这里泛型类型使用通配符表示,表次是此可以传入任意类型 */
       public <T> void show(ArrayList<T> list) {
         Iterator<T> it = list.iterator();
         while (it.hasNext()) {
            T t= it.next();
            System.out.println(t);
         }
       }
     
       public static void main(String[] agrs) {
         Demo d = new Demo();
         ArrayList<String> l1 = new ArrayList<String>();
         l1.add("abc");
         l1.add("123");
         l1.add("ased");
         d.show(l1);
         System.out.println("---------");
         ArrayList<Integer> l2 = new ArrayList<Integer>();
         l2.add(1);
         l2.add(2);
         l2.add(3);
         d.show(l2);
       }
    }
     
    结果:
    abc
    123
    ased
    ---------
    1
    2
    3


    从结果上可以看出,结果和使用通配符是一样的,这个好处可以把对象取出来,可以进行操作,T t= it.next();但是使用通配符的话,就不能进行此操作,但是通配符可以设置上下限。

    2.     通配符设置上下限

    ? extends E :?表示可以是E类型或者是E的子类,这是设置的上限

    ? super E:?表示的可以是E类型或者E的父类类型,这是设置的下限

     

    设置上限

     

    package www.fuxi.jihe;
     
    import java.util.ArrayList;
    import java.util.Iterator;
     
    class door {
      privateString name;
     
      publicdoor(String name) {
           this.name= name;
      }
     
      publicString toString() {
           returnthis.name;
      }
    }
     
    class tieDoor extends door {// 继承了door类
      publictieDoor(String name) {
           super(name);
      }
    }
     
    public class fanxingDemo {
      publicvoid show(ArrayList<? extends door> list) {// 设置类泛型的限,可以是door类型或者是door的子类型
           Iterator<?extends door> it = list.iterator();
           while(it.hasNext()) {
                 System.out.println(it.next());
           }
      }
     
      publicstatic void main(String[] args) {
           fanxingDemod = new fanxingDemo();
           ArrayList<tieDoor>list = new ArrayList<tieDoor>();
           list.add(newtieDoor("door-1"));
           list.add(newtieDoor("door-2"));
           list.add(newtieDoor("door-3"));
           d.show(list);
      }
     
    }
    结果:
    door-1
    door-2
    door-3


    设置下限:

     

    TreeSet(Comparator<?super E> comparator)
              构造一个新的空 TreeSet,它根据指定比较器进行排序。

    我们就根据这个比较器看看设置下限:

    package www.fuxi.jihe;
     
    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.TreeSet;
     
    class door {
      privateString name;
     
      publicdoor(String name) {
           this.name= name;
      }
     
      publicString toString() {
           returnthis.name;
      }
      publicString getName(){
           returnthis.name;
      }
    }
     
    class tieDoor extends door {// 继承了door类
      publictieDoor(String name) {
           super(name);
      }
    }
     class MyCom implements Comparator<door>{
      publicint compare(door o1, door o2) {
           returno1.getName().compareTo(o2.getName());
      }
       
     }
    public class fanxingDemo {
      publicstatic void main(String[] args) {
           fanxingDemod = new fanxingDemo();
           TreeSet<tieDoor>list = new TreeSet<tieDoor>(new MyCom());
           list.add(newtieDoor("door-3"));
           list.add(newtieDoor("door-1"));
           list.add(newtieDoor("door-2"));
           Iterator<tieDoor>it=list.iterator();
           while(it.hasNext()){
                 System.out.println(it.next());
           }
      }
     
    }
    结果:
    door-1
    door-2
    door-3
     



    从结果可以看出,已经比较了,但是设置的比较器是父类型,但是TreeSet集合设置的door的子类型,也可以排序,就是可以是下限或者是下限的父类型

    可以是tieDoor类型或者tieDoor的父类型,都可以进行比较

    假如又有一个类继承了door类,那么此子类对象添加到在TreeSet中,也可以使用当前的比较器进行排序。


    --------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------


  • 相关阅读:
    Zend Framework入门指引
    [技巧]枚举子集的飘逸写法
    [120120]fzyz机房聚会
    [解题报告]ural 1041 Nikifor
    [转载]二分图匹配总结
    [存档]xx09210xxx2010ACMICPC竞赛总结
    [解题报告]ural 1163 Chapaev
    [总结]勿忘本心
    [解题报告]ural 1176 Hyperchannels
    [存档]xx09210xxx2011ACMICPC竞赛总结
  • 原文地址:https://www.cnblogs.com/pangblog/p/3341900.html
Copyright © 2011-2022 走看看