zoukankan      html  css  js  c++  java
  • Java之泛型

    1. 概述
              在引入泛型之前,Java类型分为原始类型、复杂类型,其中复杂类型分为数组和类。引入泛型后,一个复杂类型就可以在细分成更多的类型。
              例如原先的类型List,现在在细分成List<Object>, List<String>等更多的类型。
              注意,现在List<Object>, List<String>是两种不同的类型,他们之间没有继承关系,即使String继承了Object。下面的代码是非法的:

    1 List<String> ls = new ArrayList<String>();
    2 List<Object> lo = ls;

             这样设计的原因在于,根据lo的声明,编译器允许你向lo中添加任意对象(例如Integer),但是此对象是List<String>,破坏了数据类型的完整性。
             在引入范型之前,要在类中的方法支持多个数据类型,就需要对方法进行重载,在引入范型后,可以解决此问题(多态),更进一步可以定义多个参数以及返回值之间的关系。例如:

    1 public void write(Integer i, Integer[] ia);
    2 public void write(Double  d, Double[] da);

    的范型版本为:

    1 public <T> void write(T t, T[] ta);

    在看下面代码:

     1 public class GenericTest {
     2 
     3     public static void main(String[] args) {
     4         List list = new ArrayList();
     5         list.add("qqyumidi");
     6         list.add("corn");
     7         list.add(100);
     8 
     9         for (int i = 0; i < list.size(); i++) {
    10             String name = (String) list.get(i); // 1
    11             System.out.println("name:" + name);
    12         }
    13     }
    14 }

          定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

    通过使用泛型,解决上面异常,修改代码如下:

     1 public class GenericTest {
     2 
     3     public static void main(String[] args) {
     4         /*
     5         List list = new ArrayList();
     6         list.add("qqyumidi");
     7         list.add("corn");
     8         list.add(100);
     9         */
    10 
    11         List<String> list = new ArrayList<String>();
    12         list.add("qqyumidi");
    13         list.add("corn");
    14         //list.add(100);   // 1  提示编译错误
    15 
    16         for (int i = 0; i < list.size(); i++) {
    17             String name = list.get(i); // 2
    18             System.out.println("name:" + name);
    19         }
    20     }
    21 }

    总结: 使用泛型可以指代任意对象类型,定义的容器所放的内容是一个统一的类型;   

    java中泛型的引入主要是为了解决两个方面的问题:
    1. 集合类型元素在运行期出现类型装换异常,引入泛型增加编译时类型的检查;(即:消除强制类型转换,提高 Java 程序的类型安全)
    2. 解决开发时重复代码的编写,能够复用算法。(比如:在类中的方法支持多个数据类型,就需要对方法进行重载)

    2. 定义泛型类

    我们直接上代码:

     1 package com.learn.chap06.sec01;
     2 
     3 public class Fdemo<T> {  // 泛型类
     4     private T a;
     5 
     6     public Fdemo(T a) {
     7         super();
     8         this.a = a;
     9     }
    10 
    11     public T getA() {
    12         return a;
    13     }
    14 
    15     public void setA(T a) {
    16         this.a = a;
    17     }
    18     
    19     public void print(){
    20         System.out.println("Obeject类型为:"+a.getClass().getName());
    21     }
    22     
    23     
    24 }
     1 package com.learn.chap06.sec01;
     2 /**
     3  * 定义泛型类    (使用泛型可以指代任意对象类型)
     4  * @author Administrator
     5  *
     6  */
     7 public class Fdemotest {
     8     
     9     public static void main(String[] args) {
    10         Fdemo<Integer> test = new Fdemo<Integer>(12);
    11         test.print();
    12         System.out.println("test="+test.getA());
    13         
    14         Fdemo<String> strFdemo = new Fdemo<String>("我是中国人");
    15         strFdemo.print();
    16         System.out.println("strFdemo="+strFdemo.getA());
    17     }
    18 }

    运行结果:

    Obeject类型为:java.lang.Integer
    test=12
    Obeject类型为:java.lang.String
    strFdemo=我是中国人

    3. 限制泛型:

    我们直接上代码:

    1 package com.learn.chap06.sec02;
    2 
    3 public class Animal {
    4     public void say() {
    5         System.out.println("它是动物");
    6     }
    7 }
     1 package com.learn.chap06.sec02;
     2 
     3 public class Dog extends Animal{
     4 
     5     @Override
     6     public void say() {
     7         // TODO Auto-generated method stub
     8         System.out.println("它是一只狗");
     9     }
    10     
    11     
    12 }
     1 package com.learn.chap06.sec02;
     2 
     3 public class Cat extends Animal{
     4 
     5     @Override
     6     public void say() {
     7         // TODO Auto-generated method stub
     8         System.out.println("它是一只猫");
     9     }
    10     
    11     
    12 }
     1 package com.learn.chap06.sec02;
     2 
     3 public class Demo<T extends Animal>{
     4     private T ob;
     5 
     6     public Demo(T ob) {
     7         super();
     8         this.ob = ob;
     9     }
    10 
    11     public T getOb() {
    12         return ob;
    13     }
    14 
    15     public void setOb(T ob) {
    16         this.ob = ob;
    17     }
    18     
    19     public void print(){
    20         System.out.println("T的类型是:"+ob.getClass().getName());
    21     }
    22 }
     1 package com.learn.chap06.sec02;
     2 /**
     3  * 限制泛型
     4  * @author Administrator
     5  *
     6  */
     7 public class Test {
     8     public static void main(String[] args) {
     9         Demo<Dog> demo = new Demo<Dog>(new Dog());
    10         //demo.say(); 
    11         demo.print();
    12         
    13         //Demo<Integer> demo = new Demo<Integer>(new Dog()); // 由于泛型定义Demo类的类型必须为Animal或其子类Dog和Cat,而Integer不是Animal的子类,所以类型被限制,即:限制泛型,导致编译报错
    14         Demo<Animal> demo2 = new Demo<Animal>(new Cat());
    15         demo2.print();
    16         
    17         Demo<Cat> demo3 = new Demo<Cat>(new Cat());
    18         demo3.print();
    19         
    20     }
    21 }

    运行结果:

    T的类型是:com.learn.chap06.sec02.Dog
    T的类型是:com.learn.chap06.sec02.Cat
    T的类型是:com.learn.chap06.sec02.Cat

    4. 通配符泛型:

    我们直接上代码:

     1 package com.learn.chap06.sec03;
     2 
     3 import com.learn.chap06.sec02.Animal;
     4 import com.learn.chap06.sec02.Cat;
     5 import com.learn.chap06.sec02.Demo;
     6 import com.learn.chap06.sec02.Dog;
     7 
     8 public class Test1 {
     9     /**
    10      * 通配符泛型
    11      * @param demo
    12      */
    13     public static void take(Demo<?> demo){ // <?> 即为:通配符泛型
    14         demo.print();
    15     }
    16     
    17     public static void main(String[] args) {
    18         Demo<Dog> demo1 = new Demo<Dog>(new Dog());
    19         take(demo1);
    20         
    21         Demo<Cat> demo2 = new Demo<Cat>(new Cat());
    22         take(demo2);
    23         
    24         Demo<Animal> demo3 = new Demo<Animal>(new Animal());
    25         take(demo3);
    26     }
    27 }

    运行结果:

    T的类型是:com.learn.chap06.sec02.Dog
    T的类型是:com.learn.chap06.sec02.Cat
    T的类型是:com.learn.chap06.sec02.Animal

    5. 泛型方法:

     1 package com.learn.chap06.sec04;
     2 
     3 public class Test {
     4     
     5     /**
     6      * 泛型方法
     7      * @param t
     8      */
     9     public  static <T> void f(T t) {
    10         System.out.println("T的类型是:"+t.getClass().getName());
    11     }
    12     
    13     public static void main(String[] args) {
    14         f(1);
    15         f("hello");
    16         f(1.0f);
    17         f(new Object());
    18     }
    19 }

    运行结果:

    T的类型是:java.lang.Integer
    T的类型是:java.lang.String
    T的类型是:java.lang.Float
    T的类型是:java.lang.Object

    现在使用泛型没问题了吧!呵呵

  • 相关阅读:
    winform+c#之窗体之间的传值 Virus
    ASP.NET 2.0 利用 checkbox获得选中行的行号, 在footer中显示 Virus
    .NET中的winform的listview控件 Virus
    我的书橱
    Expert .NET 2.0 IL Assembler·译者序一 写在一稿完成之即
    Verbal Description of Custom Attribute Value
    AddressOfCallBacks in TLS
    下一阶段Schedule
    2008 Oct MVP OpenDay 第二天 博客园聚会
    2008 Oct MVP OpenDay 第二天 颁奖·讲座·晚会
  • 原文地址:https://www.cnblogs.com/eaglezb/p/5983567.html
Copyright © 2011-2022 走看看