Java学习总结第二十九天Java泛型应用

本文介绍了Java泛型的高级应用技巧,包括如何限制泛型类型、使用通配符泛型解决类型动态确定的问题以及泛型方法的定义和使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泛型高级应用

示例:

public class GenericsFoo<T> {   
    private T x;       
    public GenericsFoo(T x) {   
        this.x = x;   
    }   
    public T getX() {   
        return x;   
    }   
    public void setX(T x) {   
        this.x = x;   
    }   
}   
public static void main(String args[]){   
        GenericsFoo<String> strFoo=new GenericsFoo<String>("Hello Generics!");   
        GenericsFoo<Double> douFoo=new GenericsFoo<Double>(new Double("33"));   
        GenericsFoo<Object> objFoo=new GenericsFoo<Object>(new Object());   
    
        System.out.println("strFoo.getX="+strFoo.getX());   
        System.out.println("douFoo.getX="+douFoo.getX());   
        System.out.println("objFoo.getX="+objFoo.getX());   
    }   
}  

运行结果: 
strFoo.getX=Hello Generics! 
douFoo.getX=33.0 
objFoo.getX=java.lang.Object@19821f 

和使用“Object泛型”方式实现结果的完全一样,但是这个Demo简单多了,里面没有强制类型转换信息。

 

1、限制泛型的可用类型 
在上面的例子中,由于没有限制class GenericsFoo<T>类型持有者T的范围,实际上这里的限定类型相当于Object,这和“Object泛型”实质是一样的。限制比如我们要限制T为集合接口类型。只需要这么做: 
class GenericsFoo<T extends Collection>,这样类中的泛型T只能是Collection接口的实现类,传入非Collection接口编译会出错。 
注意:<T extends Collection>这里的限定使用关键字 extends,后面可以是类也可以是接口。但这里的extends已经不是继承的含义了,应该理解为T类型是实现Collection接口的类型,或者T是继承了XX类的类型。

下面继续对上面的例子改进,我只要实现了集合接口的类型: 
public class CollectionGenFoo<T extends Collection> {   
    private T x;   
    public CollectionGenFoo(T x) {   
        this.x = x;   
    }   
    public T getX() {   
        return x;   
    }   
    public void setX(T x) {   
        this.x = x;   
    }   
}  

实例化的时候可以这么写: 
public class CollectionGenFooDemo {   
    public static void main(String args[]) {   
        CollectionGenFoo<ArrayList> listFoo = null;   
        listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());   
        //出错了,不让这么干。   
//        CollectionGenFoo<Collection> listFoo = null;   
//        listFoo=new CollectionGenFoo<ArrayList>(new ArrayList());   
        System.out.println("实例化成功!");   
    }   
}  

当前看到的这个写法是可以编译通过,并运行成功。可是注释掉的两行加上就出错了,因为<T extends Collection>这么定义类型的时候,就限定了构造此类实例的时候T是确定的一个类型,这个类型实现了Collection接口,但是实现 Collection接口的类很多很多,如果针对每一种都要写出具体的子类类型,那也太麻烦了,我干脆还不如用Object通用一下。别急,泛型针对这种情况还有更好的解决方案,那就是“通配符泛型”。

 

2、通配符泛型 
为了解决类型被限制死了不能动态根据实例来确定的缺点,引入了“通配符泛型”,针对上面的例子,使用通配泛型格式为<? extends Collection>,“?”代表未知类型,这个类型是实现Collection接口。那么上面实现的方式可以写为: 
public class CollectionGenFooDemo {   
    public static void main(String args[]) {   
        CollectionGenFoo<ArrayList> listFoo = null;   
        listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());   
        //现在不会出错了   
        CollectionGenFoo<? extends Collection> listFoo11 =  new CollectionGenFoo<ArrayList>();

 CollectionGenFoo<? extends Collection> listFoo12 =  new CollectionGenFoo<LinkedList>();
        System.out.println("实例化成功!");   
    }   
}  

 

注意:
1、如果只指定了<?>,而没有extends,则默认是允许Object及其下的任何Java类了。也就是任意类。
2、通配符泛型不单可以向下限制,如<? extends Collection>,还可以向上限制,如<? super Double>,表示类型只能接受Double及其上层父类类型,如Number、Object类型的实例。
3、泛型类定义可以有多个泛型参数,中间用逗号隔开,还可以定义泛型接口,泛型方法。这些都泛型类中泛型的使用规则类似。

 

3.泛型方法
  是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。如:   

public class ExampleA {   

    public <T> void f(T x) {              

         System.out.println(x.getClass().getName());   

     }   

     public static void main(String[] args) {  

         ExampleA ea = new ExampleA();   

         ea.f(" ");   

         ea.f(10);   

         ea.f('a');   

         ea.f(ea);   

      }   

}   

输出结果:

java.lang.String   

java.lang.Integer   

java.lang.Character   

ExampleA   使用泛型方法时,不必指明参数类型,编译器会自己找出具体的类型。泛型方法除了定义不同,调用就像普通方法一样。   需要注意,一个static方法,无法访问泛型类的类型参数,所以,若要static方法需要使用泛型能力,必须使其成为泛型方法。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值