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的子类,但不确定是什么类的实例,编译器不让您加入信息,理由是,如果可以加入信息的話,那么您就得記得取回的实例是什么类型,然后转换为原來的类型方可进行操作,这就失去了使用泛型的意义。

  • 相关阅读:
    DNS 访问 Service【转】
    Service IP 原理【转】
    通过 Service 访问 Pod【转】
    定时执行 Job【转】
    并行执行 Job【转】
    Job 失败了怎么办?【转】
    用 k8s 运行一次性任务【转】
    运行自己的 DaemonSet【转】
    python之路——递归函数
    尝试加载 Oracle 客户端库时引发 BadImageFormatException
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/4216818.html
Copyright © 2011-2022 走看看