Java 逆变和协变关系

Java 逆变和协变关系

代码如下:

package 测试;

import java.util.ArrayList;
import java.util.List;

class{
	String A;

	public(String a)
	{
		super();
		A = a;
	}

	public String getA()
	{
		return A;
	}

	public void setA(
			String a)
	{
		A = a;
	}
	
}
class1 extends{
	
	public String getA1()
	{
		return A1;
	}

	public void setA1(
			String a1)
	{
		A1 = a1;
	}

	public1(String a, String a1)
	{
		super(a);
		A1 = a1;
	}

	String  A1;
}
class2 extends{
	
	public String getB()
	{
		return B;
	}

	public void setB(
			String b)
	{
		B = b;
	}

	public2(String a, String b)
	{
		super(a);
		B = b;
	}

	String B;
}

public class 逆变协变
{
	public static void main(
			String[] args)
	{
		/* 不适用通配符,单纯的泛型是不能实现协变的! */
//		List<子1> list = new ArrayList<父>();
		/* 不使用通配符,淡村的泛型是不能实现逆变的! */
//		List<父> list = new ArrayList<子1>();
		
		/**
		 * 下面使用通配符来实现协变和逆变
		 * 尖括号<>内元素继承关系对应通配符即可
		 */
		List<? extends> list1 = new ArrayList<1>();/* 使用通配符就能成功赋值,实现协变 */
		/* 下面不能编译通过,因为对于list1来说,T他只知道是父的子类,但是不知道是哪一个具体的子类 */
		/* 当然下面都是可以强制类型转换Cast来实现对get类型的转换的,但是这样只能解决编译不报错,但是运行会报错。 */
		/**
		 * 最高父类就是 父 
		 * 你再怎么取元素最高只能去到父!
		 * 所以可以用父去接受元素就一定能成功!!
		 */
		
		/* 因为list1容器中最高阶的类就是 父 ,没有比他更高阶的了,所以当然能用最高阶的类去接受容器里面的元素 */
		/* 因为 赋值关系中只允许: 高阶类 x = new 低阶类()!! */
		/* 所以既然 父已经是最高阶类了,所以上面的赋值关系就一定成立,一定赋值能成功,所以不会报错 */
//		子1 x = list1.get(0); 
//		子2 x = list1.get(0);
		
		/* 能get不能add */
//		list1.add(new 子1("1", "1")); //有毛病,不能add
		父 x = list1.get(0); /* 没毛病,可以get */
		
		/**
		 * 最高父类就是 Object
		 * 你能取到的元素可能最高是Object!!甚至还有其他低阶的父类
		 * 所以这种情况下不能用低阶类去取!!当然只能用Object去取,但是没有意义
		 */
		List<? super1> list2 = new ArrayList<>();/* 使用通配符就能成功赋值,实现逆变 */
		/* 能add不能get */
		/* 而且只能添加“子1”这个类型 */  
		/* 因为list2中最低阶类就是 子1 ,如果你放比他高阶的类就不能完成转换!! */
		/* 因为只要不是add最低阶的类进去,就一定存在一个比这个最低阶还要低阶的类不能完成下面的赋值操作!! */
		/* 因为 赋值关系中只允许: 高阶类 x = new 低阶类()!! */
		list2.add(new1("1", "1")); /* 没毛病,可以add */
		list2.add((1) new Object());
		list2.add((1) new(""));
		
		/* 当然下面都是可以强制类型转换Cast来实现对get类型的转换的,但是这样只能解决编译不报错,运行会报错。 */
		//父 x1 = list2.get(0); /* 有毛病,不能get */
		//子1 x2 = list2.get(0);/* 有毛病,不能get */
	}
	
}

总结:

  • 只要new出来的容器之间的元素满足 通配符 ?extends 或者是 ? super就能进行赋值。这正是通配符实现的逆变和协变的效果
  • ?extends XX 决定了容器内元素的最高阶层就是 XX,因为类的赋值关系永远满足: 高阶类 A= new 低阶类()!! 所以可能用XX这个最高阶的类去接受list容器get出来的元素而永远不会报错,因为永远满足:XX 变量 = list.get(index) 。所以是可以get的但是不能add,因为extends决定的是天花板,不是地板,所以你的添加关系中add只有加入最低阶层的类(这种类不存在) 才能满足赋值的恒成立性!
  • ? super XX 决定了容器内元素的最低阶层是 XX,因为类的赋值关系 永远满足: 高阶类 A= new 低阶类()!! 这里面最高阶层达到了顶层的Object,所以要使得类赋值关系的恒成立,就是说get出来的东西能够赋值成功,只能用Object去接受get出来的变量。然而这没意义。同理,我们add进去的也必须是最底阶层的类才能使得赋值关系恒成立,也就是只能add 进去XX类的实例。
  • 所以: ?extends 可以get不能add。 ?supers 可以add不能get。。。(强制类型转换除外,Object接受变量除外,这两种都没有意义,甚至会运行报错)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值