Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 639|回复: 0

Java泛型深究

[复制链接]

该用户从未签到

发表于 2011-9-13 20:23:44 | 显示全部楼层 |阅读模式
java SE1.5中,增加了一个新的特性:泛型。什么是泛型呢?简单来说,就是泛泛的指定对象所操作的类型,而不像通常方式一样使用某种固定的类型去指定。泛型的本质就是将所操作的数据类型参数化,也就是说,该数据类型被指定为一个参数。这种参数类型可以使用在类、接口以及方法定义中。有点枚举的意思,
一、    泛型的作用
     在以往的J2SE中,没有泛型的情况下,通常是使用Object类型来进行多种类型数据的操作。这个时候操作最多的就是针对该Object进行数据的强制转换,而这种转换是基于开发者对该数据类型明确的情况下进行的(比如将Object型转换为String型)。倘若类型不一致,编译器在编译过程中不会报错,但在运行时会出错。
    使用泛型的好处在于,它在编译的时候进行类型安全检查,并且在运行时所有的转换都是强制的,隐式的,大大提高了代码的重用率。
二、 泛型的简单例子
首先,我们来看看下面两个普通的class定义
public class getString {
private String myStr;

public String getStr() {
    return myStr;
}

public void setStr(str) {
    myStr = str;
}
}

public class getDouble {
private Double myDou;

public Double getDou() {
    return myDou;
}

public void setDou(dou) {
    myDou = dou;
}
          }

    这两个class除了所操作的数据类型不一致,其他机能都是相同的。现在,我们可以使用泛型来将上面两个class合并为一个,从而提高代码利用率,减少代码量。
        public class getObj<T> {
            private T myObj ;
           
            public T getObj() {
                return myObj;
            }

            public void setObj<T obj> {
                 myObj = obj;
              }
        }

    那么,使用了泛型后,如何生成这个class的实例来进行操作呢?请看下面的代码:
        getObj<String> strObj = new getObj<String>();
        strObj.setObj(“Hello Nissay”);
        System.out.println(strObj.getObj());

         getObj<Double> douObj = new getObj<Double>();
         douObj.setObj(new Double(“116023”));
         System.out.println(douObj.getObj());

三、 例子分析
现在我们来分析上面那段蓝色字体的代码:
1、<T>是泛型的标记,当然可以使用别的名字,比如。使用<T>声明一个泛型的引用,从而可以在class、方法及接口中使用它进行数据定义,参数传递。
2、<T>在声明的时候相当于一个有意义的数据类型,编译过程中不会发生错误;在实例化时,将其用一个具体的数据类型进行替代,从而就可以满足不用需求。

四、泛型的规则和限制
通过上述的例子,我们简单理解了泛型的含义。在使用泛型时,请注意其使用规则和限制,如下:
1、泛型的参数类型只能是类(class)类型,而不能是简单类型。
      比如,<int>是不可使用的。
2、可以声明多个泛型参数类型,比如<T, P,Q…>,同时还可以嵌套泛型,例如:<List<String>>
3、泛型的参数类型可以使用extends语句,例如<T extends superclass>。
4、泛型的参数类型可以使用super语句,例如< T super childclass>。
5、泛型还可以使用通配符,例如<? extends ArrayList>

五、扩展
1、extends语句
使用extends语句将限制泛型参数的适用范围。例如:
<T extends collection> ,则表示该泛型参数的使用范围是所有实现了collection接口的calss。如果传入一个<String>则程序编译出错。
2、super语句
super语句的作用与extends一样,都是限制泛型参数的适用范围。区别在于,super是限制泛型参数只能是指定该class的上层父类。
例如<T super List>,表示该泛型参数只能是List和List的上层父类。
3、通配符
使用通配符的目的是为了解决泛型参数被限制死了不能动态根据实例来确定的缺点。
举个例子:public class SampleClass < T extends S> {…}
假如A,B,C,…Z这26个class都实现了S接口。我们使用时需要使用到这26个class类型的泛型参数。那实例化的时候怎么办呢?依次写下
SampleClass<A> a = new SampleClass();
SampleClass<B> a = new SampleClass();

SampleClass<Z> a = new SampleClass();
这显然很冗余,还不如使用Object而不使用泛型,呵呵,是吧?
别着急,咱们使用通配符,就OK了。
SampleClass<? Extends S> sc = new SampleClass();

普通泛型
class Point< T>{  // 此处可以随便写标识符号,T是type的简称   
    private T var ; // var的类型由T指定,即:由外部指定   
    public T getVar(){ // 返回值的类型由外部决定   
        return var ;   
    }   
    public void setVar(T var){ // 设置的类型也由外部决定   
        this.var = var ;   
    }  
};  
public class GenericsDemo06{   
    public static void main(String args[]){   
        Point< String> p = new Point< String>() ; // 里面的var类型为String类型   
        p.setVar("it") ;  // 设置字符串   
        System.out.println(p.getVar().length()) ; // 取得字符串的长度   
    }  
};

class Notepad< K,V>{  // 此处指定了两个泛型类型   
    private K key ;  // 此变量的类型由外部决定   
    private V value ; // 此变量的类型由外部决定   
    public K getKey(){   
        return this.key ;   
    }   
    public V getValue(){   
        return this.value ;   
    }   
    public void setKey(K key){   
        this.key = key ;   
    }   
    public void setValue(V value){   
        this.value = value ;   
    }  
};
public class GenericsDemo09{   
    public static void main(String args[]){   
        Notepad< String,Integer> t = null ;  // 定义两个泛型类型的对象   
        t = new Notepad< String,Integer>() ;  // 里面的key为String,value为Integer   
        t.setKey("汤姆") ;  // 设置第一个内容   
        t.setValue(20) ;   // 设置第二个内容   
        System.out.print("姓名;" + t.getKey()) ;  // 取得信息   
        System.out.print(",年龄;" + t.getValue()) ;  // 取得信息   
    }  
};   
通配符
class Info< T>{   
    private T var ;  // 定义泛型变量   
    public void setVar(T var){   
        this.var = var ;   
    }   
    public T getVar(){   
        return this.var ;   
    }   
    public String toString(){ // 直接打印   
        return this.var.toString() ;   
    }  
};  
public class GenericsDemo14{   
    public static void main(String args[]){   
        Info< String> i = new Info< String>() ;  // 使用String为泛型类型   
        i.setVar("it") ;       // 设置内容   
        fun(i) ;   
    }   
    public static void fun(Info< ?> temp){  // 可以接收任意的泛型对象   
        System.out.println("内容:" + temp) ;   
    }  
};   

受限泛型
class Info< T>{   
    private T var ;  // 定义泛型变量   
    public void setVar(T var){   
        this.var = var ;   
    }   
    public T getVar(){   
        return this.var ;   
    }   
    public String toString(){ // 直接打印   
        return this.var.toString() ;   
    }  
};  
public class GenericsDemo17{   
    public static void main(String args[]){   
        Info< Integer> i1 = new Info< Integer>() ;  // 声明Integer的泛型对象   
        Info< Float> i2 = new Info< Float>() ;   // 声明Float的泛型对象   
        i1.setVar(30) ;         // 设置整数,自动装箱   
        i2.setVar(30.1f) ;        // 设置小数,自动装箱   
        fun(i1) ;   
        fun(i2) ;   
    }   
    public static void fun(Info< ? extends Number> temp){ // 只能接收Number及其Number的子类   
        System.out.print(temp + "、") ;   
    }  
};

class Info< T>{   
    private T var ;  // 定义泛型变量   
    public void setVar(T var){   
        this.var = var ;   
    }   
    public T getVar(){   
        return this.var ;   
    }   
    public String toString(){ // 直接打印   
        return this.var.toString() ;   
    }  
};  
public class GenericsDemo21{   
    public static void main(String args[]){   
        Info< String> i1 = new Info< String>() ;  // 声明String的泛型对象   
        Info< Object> i2 = new Info< Object>() ;  // 声明Object的泛型对象   
        i1.setVar("hello") ;   
        i2.setVar(new Object()) ;   
        fun(i1) ;   
        fun(i2) ;   
    }   
    public static void fun(Info< ? super String> temp){ // 只能接收String或Object类型的泛型   
        System.out.print(temp + "、") ;   
    }  
};   
Java泛型无法向上转型
class Info< T>{   
    private T var ;  // 定义泛型变量   
    public void setVar(T var){   
        this.var = var ;   
    }   
    public T getVar(){   
        return this.var ;   
    }   
    public String toString(){ // 直接打印   
        return this.var.toString() ;   
    }  
};  
public class GenericsDemo23{   
    public static void main(String args[]){   
        Info< String> i1 = new Info< String>() ;  // 泛型类型为String   
        Info< Object> i2 = null ;   
        i2 = i1 ;        //这句会出错
        incompatible types   
    }  
};   
Java泛型接口
interface Info< T>{  // 在接口上定义泛型   
    public T getVar() ; // 定义抽象方法,抽象方法的返回值就是泛型类型  
}  
class InfoImpl< T> implements Info< T>{ // 定义泛型接口的子类   
    private T var ;    // 定义属性   
    public InfoImpl(T var){  // 通过构造方法设置属性内容   
        this.setVar(var) ;   
    }   
    public void setVar(T var){   
        this.var = var ;   
    }   
    public T getVar(){   
        return this.var ;   
    }  
};  
public class GenericsDemo24{   
    public static void main(String arsg[]){   
        Info< String> i = null;  // 声明接口对象   
        i = new InfoImpl< String>("汤姆") ; // 通过子类实例化对象   
        System.out.println("内容:" + i.getVar()) ;   
    }  
};

interface Info< T>{  // 在接口上定义泛型   
    public T getVar() ; // 定义抽象方法,抽象方法的返回值就是泛型类型  
}
class InfoImpl implements Info< String>{ // 定义泛型接口的子类   
    private String var ;    // 定义属性   
    public InfoImpl(String var){  // 通过构造方法设置属性内容   
        this.setVar(var) ;   
    }   
    public void setVar(String var){   
        this.var = var ;   
    }   
    public String getVar(){   
        return this.var ;   
    }  
};  
public class GenericsDemo25{   
    public static void main(String arsg[]){   
        Info i = null;  // 声明接口对象   
        i = new InfoImpl("汤姆") ; // 通过子类实例化对象   
        System.out.println("内容:" + i.getVar()) ;   
    }  
};
Java泛型方法
class Demo{   
    public < T> T fun(T t){   // 可以接收任意类型的数据   
        return t ;     // 直接把参数返回   
    }  
};  
public class GenericsDemo26{   
    public static void main(String args[]){   
        Demo d = new Demo() ; // 实例化Demo对象   
        String str = d.fun("汤姆") ; // 传递字符串   
        int i = d.fun(30) ;  // 传递数字,自动装箱   
        System.out.println(str) ; // 输出内容   
        System.out.println(i) ;  // 输出内容   
    }  
};   
通过泛型方法返回泛型类型实例
class Info< T extends Number>{ // 指定上限,只能是数字类型   
    private T var ;  // 此类型由外部决定   
    public T getVar(){   
        return this.var ;   
    }   
    public void setVar(T var){   
        this.var = var ;   
    }   
    public String toString(){  // 覆写Object类中的toString()方法   
        return this.var.toString() ;   
    }  
};  
public class GenericsDemo27{   
    public static void main(String args[]){   
        Info< Integer> i = fun(30) ;   
        System.out.println(i.getVar()) ;   
    }   
    public static < T extends Number> Info< T> fun(T param){//方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定   
        Info< T> temp = new Info< T>() ;  // 根据传入的数据类型实例化Info   
        temp.setVar(param) ;  // 将传递的内容设置到Info对象的var属性之中   
        return temp ; // 返回实例化对象   
    }  
};   
使用泛型统一传入的参数类型
class Info< T>{ // 指定上限,只能是数字类型
    private T var ;  // 此类型由外部决定   
    public T getVar(){   
        return this.var ;   
    }   
    public void setVar(T var){   
        this.var = var ;   
    }   
    public String toString(){  // 覆写Object类中的toString()方法   
        return this.var.toString() ;   
    }  
};  
public class GenericsDemo28{   
    public static void main(String args[]){   
        Info< String> i1 = new Info< String>() ;   
        Info< String> i2 = new Info< String>() ;   
        i1.setVar("HELLO") ;  // 设置内容   
        i2.setVar("汤姆") ;  // 设置内容   
        add(i1,i2) ;   
    }   
    public static < T> void add(Info< T> i1,Info< T> i2){   
        System.out.println(i1.getVar() + " " + i2.getVar()) ;   
    }  
};   
Java泛型数组
public class GenericsDemo30{   
    public static void main(String args[]){   
        Integer i[] = fun1(1,2,3,4,5,6) ; // 返回泛型数组   
        fun2(i) ;   
    }   
    public static < T> T[] fun1(T...arg){ // 接收可变参数   
        return arg ;   // 返回泛型数组   
    }   
    public static < T> void fun2(T param[]){ // 输出   
        System.out.print("接收泛型数组:") ;   
        for(T t:param){     
            System.out.print(t + "、") ;   
        }   
    }  
};   
Java泛型的嵌套设置
class Info< T,V>{  // 接收两个泛型类型   
    private T var ;   
    private V value ;   
    public Info(T var,V value){   
        this.setVar(var) ;   
        this.setValue(value) ;   
    }   
    public void setVar(T var){   
        this.var = var ;   
    }   
    public void setValue(V value){   
        this.value = value ;   
    }   
    public T getVar(){   
        return this.var ;   
    }   
    public V getValue(){   
        return this.value ;   
    }  
};  
class Demo< S>{   
    private S info ;   
    public Demo(S info){   
        this.setInfo(info) ;   
    }   
    public void setInfo(S info){   
        this.info = info ;   
    }   
    public S getInfo(){   
        return this.info ;   
    }  
};  
public class GenericsDemo31{   
    public static void main(String args[]){   
        Demo< Info< String,Integer>> d = null ;  // 将Info作为Demo的泛型类型   
        Info< String,Integer> i = null ; // Info指定两个泛型类型   
        i = new Info< String,Integer>("汤姆",30) ;  // 实例化Info对象   
        d = new Demo< Info< String,Integer>>(i) ; // 在Demo类中设置Info类的对象   
        System.out.println("内容一:" + d.getInfo().getVar()) ;   
        System.out.println("内容二:" + d.getInfo().getValue()) ;   
    }  
};  

[/td][/tr][/table]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-5-2 06:24 , Processed in 0.424018 second(s), 35 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表