Java中泛型的理解(二)

主要总结的内容通配符、受限泛型、泛型与子类继承的限制
一.通配符“?”
在开发中对象的引用传递是最常见的,如果在泛型类的操作中,在进行引用传递的时候泛型类型必须匹配才可以传递,否则无法传递
我们看如下程序:
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编程思想
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值