欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

读编写高质量代码整理(九)-警惕泛型不能协变和逆变

程序员文章站 2024-03-14 19:37:34
...

先引进两个名词“协变”、“逆变”

协变——用一个窄类型替换宽类型

逆变——用宽类型替换窄类型

 协变代码如下:

public class Base {
	public Number doStuff() {
		return 0;
	}
}
class Sub extends Base {

	@Override
	public Integer doStuff() {
		return 0;
	}
}

逆变代码如下:

public class Base {
	public void doStuff(Integer i) {
	}
}
class Sub extends Base {
	@Override
	public void doStuff(Integer i) {
	}
	// overload
	public void doStuff(Number num) {
	}
}

 协变即为多态,作者如是说“在java世界里,重复发明*的事情多了去了”!哈哈

但是。。。

泛型不支持协变,我很纳闷,为什么呢?

java机制问题,java为了保证运行时安全,必须保证泛型的类型是一致的,即使是父子类都不可以。

不过,泛型提供了一种通配符(Wildcard)模拟协变,代码如下:

List<? extends Number> ln = new ArrayList<Integer>();

  ? extends Number是什么意思呢?extends是继承的依稀,某某继承Number的意思是说,我只要是Number的一个子类就可以了,by the way,? super Integer是什么意思呢?猜出来了了,只要是Integer的父类皆可,这两者extends super合起来就构成泛型的边界喽!

泛型不支持逆变!同理可以通过通配符模拟,代码如下:

 

List<? super Integer> ln = new ArrayList<Number>();