zoukankan      html  css  js  c++  java
  • 关于泛型

    泛型:

    泛型是JDK1.5中一个最重要的特性,通过引入泛型,我们将获得编译时类型的安全,和运行时更小的抛出ClassCastexceptions的可能.在JDK1.5中,你可以声明一个集合接收或者返回的对象的类型.

     泛型之前:

    类别定义时的逻辑完全一样,只是里面成员变量的类型不同.

    如果需要多个相似的类,需要定义多个文件,不同的只是变量的类别,而逻辑是完全一样的.

    IntergerFoo.java

     1 public class IntegerFoo{
     2     private Integer foo;
     3 
     4     public Integer getFoo(){
     5         return foo;
     6     }
     7 
     8     public void setFoo(Integer foo){
     9         this.foo = foo;
    10     }
    11 }

    BooleanFoo.java

     1 public class BooleanFoo{
     2     private Boolean foo;
     3 
     4     public Boolean getFoo()    {
     5         return foo;
     6     }
     7 
     8     public void setFoo(Boolean foo){
     9         this.foo = foo;
    10     }
    11 }

    如果有很多类型的话想用一个类型来替代以上等的类型怎么办,只能用Object类.

    ObjectFoo.java

     1 public class ObjectFoo{
     2     private Object foo;
     3 
     4     public Object getFoo(){
     5         return foo;
     6     }
     7 
     8     public void setFoo(Object foo){
     9         this.foo = foo;
    10     }
    11     
    12     public static void main(String[] args){
    13         ObjectFoo foo1 = new ObjectFoo();
    14         ObjectFoo foo2 = new ObjectFoo();
    15         
    16         foo1.setFoo(new Boolean(false));
    17         Boolean b = (Boolean)foo1.getFoo();
    18         
    19         foo2.setFoo(new Integer(10));
    20         Integer i = (Integer)foo2.getFoo();
    21         
    22         ObjectFoo foo3 = new ObjectFoo();
    23         foo3.setFoo(new Boolean(false));
    24         
    25         String str = (String)foo3.getFoo();
    26         //这个时候编译不会报错,但是运行的时候Object不能转换成String类型的,一定会出错
    27         //java.lang.ClassCastException: java.lang.Boolean cannot be caast to java.lang.String
    28     }
    29 }

    定义泛型类别:

    如果使用泛型,只要代码在编译时没有出现警告,就不会遇到运行时ClassCastException

    所谓泛型就是变量的类型参数化(不是变量本身,是变量的类型).

    GenericFoo.java

     1 public class GenericFoo<T>{
     2     private T foo;
     3     
     4     public T getFoo(){
     5         return foo;
     6     }
     7 
     8     public void setFoo(T foo){
     9         this.foo = foo;
    10     }
    11 
    12     public static void main(String[] args){
    13         GenericFoo<Boolean> foo1 = new GenericFoo<Boolean>();
    14         GenericFoo<Integer> foo2 = new GenericFoo<Integer>();
    15         
    16         foo1.setFoo(new Boolean(false));
    17         foo2.setFoo(new Integer(3));
    18         
    19         Boolean b = foo1.getFoo();
    20         Integer i = foo2.getFoo();
    21         
    22         System.out.println(b);//打印输出:false
    23         System.out.println(i);//打印输出:3
    24         
    25         //foo1 = foo2;
    26         //报错Type mismatch: cannot convert from GenericFoo<Integer> to GenericFoo<Boolean>
    27         
    28         GenericFoo a = new GenericFoo();
    29         a.setFoo("hello");
    30         
    31         String str = (String)a.getFoo();
    32         System.out.println(str);//输出:hello
    33     }
    34 }

     Generic.java

     1 public class Generic<T1, T2>{
     2     private T1 foo1;
     3     
     4     private T2 foo2;
     5 
     6     public T1 getFoo1(){
     7         return foo1;
     8     }
     9 
    10     public void setFoo1(T1 foo1){
    11         this.foo1 = foo1;
    12     }
    13 
    14     public T2 getFoo2(){
    15         return foo2;
    16     }
    17 
    18     public void setFoo2(T2 foo2){
    19         this.foo2 = foo2;
    20     }
    21     
    22     public static void main(String[] args){
    23         Generic<Integer, Boolean> foo = new Generic<Integer, Boolean>();
    24         
    25         foo.setFoo1(new Integer(-20));
    26         foo.setFoo2(new Boolean(false));
    27         
    28         System.out.println(foo.getFoo1());
    29         System.out.println(foo.getFoo2());
    30     }
    31 }

    打印输出:

    -20
    false

    Generic2.java

     1 public class Generic2<T>{
     2     private T[] fooArray;
     3     //泛型数组
     4 
     5     public T[] getFooArray(){
     6         return fooArray;
     7     }
     8 
     9     public void setFooArray(T[] fooArray){
    10         this.fooArray = fooArray;
    11     }
    12     
    13     public static void main(String[] args){
    14         Generic2<String> foo = new Generic2<String>();
    15         
    16         String[] str1 = {"hello", "world", "welcome"};
    17         String[] str2 = null;
    18         
    19         foo.setFooArray(str1);
    20         
    21         str2 = foo.getFooArray();
    22         
    23         for(int i = 0; i < str2.length; i++){
    24             System.out.println(str2[i]);
    25         }
    26     }
    27 }

    打印输出:

    hello
    world
    welcome

    SimpleCollection.java

     1 public class SimpleCollection<T>{
     2     private T[] objArr;
     3     
     4     private int index = 0;
     5     
     6     public SimpleCollection(){
     7         objArr = (T[])new Object[10];
     8         //这个时候编译器会有一个警告:
     9         //Type safety: Unchecked cast from Object[] to T[]
    10         //这个时候老师领着看的ArrayList的源码中的get()方法
    11         
    12         //objArr = new T[10];
    13         //报错:Cannot create a generic array of T
    14         //语法上不允许这样创建一个泛型数组.这个时候怎么办?
    15         //只能用Object类型.
    16         
    17     }
    18     
    19     public SimpleCollection(int capacity){
    20         objArr = (T[])new Object[capacity];
    21     }
    22     
    23     public void add(T t){
    24         objArr[index++] = t;
    25     }
    26     
    27     public int getLength(){
    28         return this.index;
    29     }
    30     
    31     public T get(int i){
    32         return objArr[i];
    33     }
    34     
    35     public static void main(String[] args){
    36         SimpleCollection<Integer> c = new SimpleCollection<Integer>();
    37         
    38         for(int i = 0; i < 10; i++){
    39             c.add(new Integer(i));
    40         }
    41         
    42         for(int i = 0; i < 10; i++){
    43             Integer in = c.get(i);
    44             
    45             System.out.println(in);
    46         }
    47     }
    48 }

    打印输出:1~9

    ArrayListTest.java

     1 public class ArrayListTest{
     2     public static void main(String[] args){
     3         List<String> list = new ArrayList<String>();
     4         
     5         list.add("a");
     6         list.add("b");
     7         list.add("c");
     8         list.add("d");
     9         //第一种遍历
    10         for(int i = 0; i < list.size(); i++){
    11             String value = list.get(i);
    12             System.out.println(value);
    13         }
    14         
    15         //第二种:使用迭代器
    16         for(Iterator<String> iter = list.iterator(); iter.hasNext();){
    17             String value = iter.next();
    18             System.out.println(value);
    19         }
    20     }
    21 }

    打印输出:两次a b c d

    SetTest.java

      1 package cn.shengsiyuan.jdk5;
      2 
      3 import java.util.HashSet;
      4 import java.util.Iterator;
      5 import java.util.Set;
      6 
      7 public class SetTest{
      8     public static void main(String[] args){
      9         Set<String> set = new HashSet<String>();
     10 
     11         set.add("aa");
     12         set.add("bb");
     13         set.add("cc");
     14 
     15         for (Iterator<String> iter = set.iterator(); iter.hasNext();){
     16             String value = iter.next();
     17             System.out.println(value);
     18         }
     19         
     20         System.out.println("----------------");
     21         
     22         Set<People> set2 = new HashSet<People>();
     23         
     24         set2.add(new People("zhangsan", 20, "beijing"));
     25         set2.add(new People("lisi", 30, "shanghai"));
     26         set2.add(new People("wangwu", 40, "tianjin"));
     27         
     28         for(Iterator<People> iter = set2.iterator(); iter.hasNext();){
     29             People people = iter.next();
     30             
     31             String name = people.getName();
     32             int age = people.getAge();
     33             String address = people.getAddress();
     34             
     35             System.out.println(name + "," + age + "," + address);
     36         }
     37     }
     38 }
     39 
     40 class People{
     41     private String name;
     42 
     43     private int age;
     44 
     45     private String address;
     46 
     47     public People(String name, int age, String address){
     48         this.name = name;
     49         this.age = age;
     50         this.address = address;
     51 
     52     }
     53 
     54     public int hashCode(){
     55         final int prime = 31;
     56         int result = 1;
     57         result = prime * result + ((address == null) ? 0 : address.hashCode());
     58         result = prime * result + age;
     59         result = prime * result + ((name == null) ? 0 : name.hashCode());
     60         return result;
     61     }
     62 
     63     public boolean equals(Object obj){
     64         if (this == obj)
     65             return true;
     66         if (obj == null)
     67             return false;
     68         if (getClass() != obj.getClass())
     69             return false;
     70         People other = (People) obj;
     71         if (address == null){
     72             if (other.address != null)
     73                 return false;
     74         }
     75         else if (!address.equals(other.address)){
     76             return false;
     77         }
     78         if (age != other.age){
     79             return false;
     80         }
     81         if (name == null){
     82             if (other.name != null){
     83                 return false;
     84             }
     85         }
     86         else if (!name.equals(other.name)){
     87             return false;
     88         }
     89         return true;
     90     }
     91 
     92     public String getName(){
     93         return name;
     94     }
     95 
     96     public void setName(String name){
     97         this.name = name;
     98     }
     99 
    100     public int getAge(){
    101         return age;
    102     }
    103 
    104     public void setAge(int age){
    105         this.age = age;
    106     }
    107 
    108     public String getAddress(){
    109         return address;
    110     }
    111 
    112     public void setAddress(String address){
    113         this.address = address;
    114     }
    115 }

    aa
    bb
    cc
    ----------------
    wangwu,40,tianjin
    zhangsan,20,beijing
    lisi,30,shanghai

    MapTest.java

     1 public class MapTest{
     2     public static void main(String[] args){
     3         Map<String, String> map = new HashMap<String, String>();
     4 
     5         map.put("a", "aa");
     6         map.put("b", "bb");
     7         map.put("c", "cc");
     8         map.put("d", "dd");
     9 
    10         Set<String> set = map.keySet();
    11 
    12         for (Iterator<String> iter = set.iterator(); iter.hasNext();){
    13             String key = iter.next();
    14             String value = map.get(key);
    15 
    16             System.out.println(key + ":" + value);
    17         }
    18 
    19         System.out.println("----------------------------------");
    20 
    21         Set<Map.Entry<String, String>> set2 = map.entrySet();
    22 
    23         for (Iterator<Map.Entry<String, String>> iter = set2.iterator(); iter
    24                 .hasNext();){
    25             Map.Entry<String, String> entry = iter.next();
    26 
    27             String key = entry.getKey();
    28             String value = entry.getValue();
    29 
    30             System.out.println(key + ":" + value);
    31         }
    32     }
    33 }

    d:dd
    b:bb
    c:cc
    a:aa
    ----------------------------------
    d:dd
    b:bb
    c:cc
    a:aa

    限制泛型可用类型:

    在定义泛型类别时,预设可以使用任何的类型来实例化泛型类型中的类型,但是如果想要限制使用泛型类别时,只能用某个特定类型或者是其子类才能实例化该类型时,可以再定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口.

    当没有指定泛型继承的类型或接口时,默认使用T extends Object,所以默认情况下任何类型都可以作为参数传入.

     ListGenericFoo.java

     1 public class ListGenericFoo<T extends List> {
     2     // 虽然这个地方List也是一个接口,但是在泛型中仍然要用extends.不能用implements.
     3     // 不管面是类还是接口都要用extends
     4     private T[] fooArray;
     5 
     6     public T[] getFooArray() {
     7         return fooArray;
     8     }
     9 
    10     public void setFooArray(T[] fooArray) {
    11         this.fooArray = fooArray;
    12     }
    13 
    14     public static void main(String[] args) {
    15         ListGenericFoo<LinkedList> foo1 = new ListGenericFoo<LinkedList>();
    16         ListGenericFoo<ArrayList> foo2 = new ListGenericFoo<ArrayList>();
    17 
    18         LinkedList[] linkedList = new LinkedList[10];
    19 
    20         foo1.setFooArray(linkedList);
    21 
    22         ArrayList[] arrayList = new ArrayList[10];
    23 
    24         foo2.setFooArray(arrayList);
    25 
    26         // ListGenericFoo<HashMap> foo3 = new ListGenericFoo<HashMap>();
    27         // 报错,HashMap和List没有关系.
    28         // Bound mismatch: The type HashMap is not a valid substitute for
    29         // the bounded parameter <T extends List> of the type ListGenericFoo<T>
    30     }
    31 }

    类型通配声明:

    现在有这么一个需求,你希望哟u一个参考名称foo可以接受所有下面的实例:

    foo = new Generic Foo<ArrayList>();
    foo = new Generic Foo<LinkedList>();

    简单的说,实例化类型持有者时,它必须是实现List的类别或其子类别,要定义这样一个名称,你可以使用"?"通配字符,并使用extends关键字限定类型持有者的形态.

    GenericFoo<? extends List> foo = null;
    foo = new GenericFoo<ArrayList>();
    foo = new GenericFoo<LinkedList>();

    GenericTest.java

     1 public class GenericTest<T>{
     2     private T foo;
     3 
     4     public T getFoo(){
     5         return foo;
     6     }
     7 
     8     public void setFoo(T foo){
     9         this.foo = foo;
    10     }
    11     
    12     public static void main(String[] args){
    13         GenericTest<? extends List> ge = null;
    14         
    15         ge = new GenericTest<ArrayList>();
    16         ge = new GenericTest<LinkedList>();
    17         
    18         //ge = new GenericTest<HashMap>();
    19         
    20         GenericTest<? super List> ge2 = null;
    21         //这种super的非常少用,传递的值的类型必须是List的父类....
    22         ge2 = new GenericTest<Object>();
    23         
    24         //ge2 = new GenericTest<ArrayList>();
    25         //Type mismatch: cannot convert from GenericTest<ArrayList> to GenericTest<? super List>
    26         
    27         GenericTest<String> ge3 = new GenericTest<String>();
    28         ge3.setFoo("hello world");
    29         //GenericTest<? extends Object> ge4 = ge3;
    30         //如果后面是Object的话可以简写成一个问号"?"
    31         GenericTest<?> ge4 = ge3;
    32         System.out.println(ge4.getFoo());//打印输出:null
    33         
    34         
    35         ge4.setFoo(null);
    36         System.out.println(ge4.getFoo());//打印输出:null
    37         //ge4.setFoo("welcome");
    38         //eclipse的提示错误信息:The method setFoo(capture#7-of ?) 
    39         //in the type GenericTest<capture#7-of ?> is not applicable for the arguments (String)
    40         //这个错误信息不好理解.老师的解释是,当你上面GenericTest<? extends Object> ge4 的时候,编译器知道ge4的类型是
    41         //Object或者其子类.但是当你进行ge4.setFoo("welcome");时候,当进行get的时候必须是一个String类型的,这个和泛型的
    42         //的初衷想违背,所以是错误的.
    43         

    使用<?>或是<? extends SomeClass>的声明方式,意味著您只能通过该名称來取得所参考实例的信息,或者是移除某些信息,但不能增加它的信息,因为只知道当中放置的是SomeClass的子类,但不确定是什么类的实例,编译器不让您加入信息,理由是,如果可以加入信息的話,那么您就得記得取回的实例是什么类型,然后转换为原來的类型方可进行操作,这就失去了使用泛型的意义。

  • 相关阅读:
    在Centos 7下编译openwrt+njit-client
    开博随笔
    Chapter 6. Statements
    Chapter 4. Arrays and Pointers
    Chapter 3. Library Types
    Chapter 2.  Variables and Basic Types
    关于stm32不常用的中断,如何添加, 比如timer10 timer11等
    keil 报错 expected an identifier
    案例分析 串口的地不要接到电源上 会烧掉
    案例分析 CAN OPEN 调试记录 进度
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/4216818.html
Copyright © 2011-2022 走看看