Java中泛型的理解(二)

来源:互联网 发布:手机淘宝怎么看优惠券 编辑:程序博客网 时间:2024/04/30 08:35
主要总结的内容通配符、受限泛型、泛型与子类继承的限制
一.通配符“?”
在开发中对象的引用传递是最常见的,如果在泛型类的操作中,在进行引用传递的时候泛型类型必须匹配才可以传递,否则无法传递
我们看如下程序:
class Info<T>{private T var;//var的类型由T指定,即:由外部指定public T getVar(){//返回值类型由外部决定return var;}public void setVar(T var){//设置类型也由外部决定this.var = var;}public String toString(){return this.var.toString();}}public class GenericDemo01{public static void main(String[] args){Info<String> i = new Info<String>();    //设置String泛型                i.setVar("Jack");fun(i);}public static void fun(<Info<Object> temp){    //接收Object泛型类型数据System.out.println("内容:"+ temp);}}



可见泛型对象进行引用传递的时候,类型必须一致;在创建泛型类对象时引用类型与实例化类型泛型也必须一致。

如果例一非要传递,可以将方法参数中的泛型取消掉,这样能得出结果
public class GenericDemo01{public static void main(String[] args){Info<String> i = new Info<String>();    //设置String泛型                i.setVar("Jack");fun(i);}public static void fun(Info temp></strong>){    //接收Object泛型类型数据System.out.println("内容:"+ temp);}}

这样做虽然执行没问题,但有些不合适,因为之前已经定义了泛型了,所以我们可以使用"Info<?> temp"代码形式。表示可以接收任意泛型类型对象
class Info<T>{private T var;//var的类型由T指定,即:由外部指定public T getVar(){//返回值类型由外部决定return var;}public void setVar(T var){//设置类型也由外部决定this.var = var;}public String toString(){return this.var.toString();}}public class GenericDemo04{public static void main(String[] args){Info<String> i = new Info<String>();i.setVar("Jack");fun(i);}public static void fun(Info<?> temp){System.out.println("内容:"+ temp);}}


注意:使用"?"意味着可以接收任意的内容,但是此内容不能使用<?>修饰的泛型对象进行修改
class Info<T>{private T var;//var的类型由T指定,即:由外部指定public T getVar(){//返回值类型由外部决定return var;}public void setVar(T var){//设置类型也由外部决定this.var = var;}public String toString(){return this.var.toString();}}public class GenericDemo05{public static void main(String[] args){Info<?> i = new Info<String>();i.setVar("Jack");}}

i.setVar("Jack")对Info<?>修饰的对象进行修改,所以出现错误


所以在使用<?>只能接收,不能修改。

二.受限泛型

在引用传递中,泛型操作中也可以设置一个泛型对象的范围上限和范围下限。上限使用extends关键字声明,表示参数化类型可能是所指定的类型,或者是此类型的子类 ,而范围下限使用super进行声明,表示参数化类型可能是所指定的类型或者此类型的父类型,直至Object类。
设置上限:
    声明对象:类名称<? extends 类> 对象名称
    定义类:[访问权限]类名称<泛型标识 extends 类>{}

class Info<T>{private T var;//var的类型由T指定,即:由外部指定public T getVar(){//返回值类型由外部决定return var;}public void setVar(T var){//设置类型也由外部决定this.var = var;}public String toString(){return this.var.toString();}}public class GenericDemo06{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类及其子类System.out.println("内容:"+temp);}}


class Info<T extends Number>{private T var;//var的类型由T指定,即:由外部指定public T getVar(){//返回值类型由外部决定return var;}public void setVar(T var){//设置类型也由外部决定this.var = var;}public String toString(){return this.var.toString();}}public class GenericDemo06{public static void main(String[] args){Info<Integer> i1 = new Info<Integer>();//声明Integer的泛型对象,Integer是Number类的子类}}

在类中声明了泛型上限是Number类,所以创建泛型对象时如果生命的泛型类型不是Number的子类则会出错
设置下限:
   声明对象:类名称<? super类> 对象名称
    定义类:[访问权限]类名称<泛型标识 extends 类>{}
class Info<T>{private T var;//var的类型由T指定,即:由外部指定public T getVar(){//返回值类型由外部决定return var;}public void setVar(T var){//设置类型也由外部决定this.var = var;}public String toString(){return this.var.toString();}}public class GenericDemo08{public static void main(String[] args){Info<String> i1 = new Info<String>();Info<Object> i1 = new Info<Object>();i1.setVar("Jack");i2.setVar(new Object());fun(i1);fun(i2);}public static void fun(Info<? super String> temp){//只能接收String或Object类型对象System.out.println("内容:"+temp);}}



三.泛型与子类继承的限制

一个类的子类可以通过对象多态性,为其父类实例化,但是在泛型操作中,子类的泛型是无法使用父类的泛型类型接收的。例如:Info<String> 不能使用Info<Object>接收
注意:Info<Object> i = new Info<String>();是错误的,这不代表“不能把String类型对象赋值给一个Object”,而是说“不能将涉及String的泛型赋给涉及Object的泛型”,即这里根本不是向上转型。Java编程思想中讲解到:“ ArrayList<Fruit> flist = new ArrayList<Apple>();Apple的List不是Fruit的List,Apple的List会持有Apple和Apple的子类型,Fruit的List会持有任意类型的Fruit,Apple的Lsit在类型上不等价于Fruit的List,即使Apple是一种 Fruit类型”
参考资料:
java核心技术卷一
李兴华老师java视频讲解
java编程思想
0 0
原创粉丝点击