公孙龙说:“白马非马”。
当然,这可以理解成,“白马“和“马“不是全同的概念,白马是一种马。
但是,我要证明,白马连“一种马”都不是!
=========== 我是严肃的分割线 ============
首先,要明确,什么是“白马”。我们可以定义:
[quote]定义:如果一匹马身上的毛都是白的,那么这匹马可以称为“白马“。[/quote]
姑且认为是全白的吧,也认为我们在生活中经常可以找到这样的马。类似的,我们可以定义“黑马”、“枣红马”等等。
对于任何一匹马,我们可以从这匹马上揪下一些毛。没问题吧。
对于任何一匹吗,我们可以给这匹马添加一些毛。假设我们可以这样做吧,加上一些毛仍然是那匹马。
随便拿一匹马(不管颜色),再拿一根黑毛,加在这匹马上,得到的仍然是马。
根据李氏替换原则,我们把这匹马换成一匹白马,我们也可以往上添加一些黑毛。
但是,我们不能给他添加黑毛,因为一旦添加了,得到的就不是白马了!
这不是有问题吗,凡是马都能往上边添加黑毛,白马是马,为什么给白马加上黑毛以后,就不是白马了呢?
——+——~~#¥+@%*¥(@ 我是华丽的分割线 @(¥*%@+¥#~~——+——
Java程序员可以这样编程序:
可惜Java不允许你这样定义“白马“。Java认为,List<WhiteFur>不是List<Fur>的子类。
如果你了解Java的“协变类型”,你会想这样定义:
编译正确。
然后我们试试:
编译通不过。Java不允许从List<? extends WhiteFur>到List<WhiteFur>的转换。
如果我们这样:
furs是List<? extends WhiteFur>型的,不能添加WhiteFur类型的元素。
看样子,不进行强制类型转换,总是会出错的。
我们这样呢?
看样子没问题吧,编译也通过了。我们成功地给一只白马增加了一根黑毛。你在想,为什么不能呢?白马也是马,马可以加黑毛,白马为什么不能加黑毛呢?
for循环中,试图把myHorse.getFurs()中的成员赋给wf。这一行连警告都没有,因为编译器认为myHorse.getFurs()本来就是List<WhiteFur>型的,当然可以赋值给WhiteFur型的wf呀。
但是,运行时出错。第一根毛是白毛,没错。但是,第二根是黑毛,赋给wf时,类型转换失败。
[quote]
This is a 'WhiteFur'
Exception in thread "main" java.lang.ClassCastException: baima.BlackFur cannot be cast to baima.WhiteFur
at baima.BaimaTest.main(BaimaTest.java:41)
[/quote]
.......................我是无奈的分割线......................
好了,你说,白马到底是不是马呢?
参考:http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
当然,这可以理解成,“白马“和“马“不是全同的概念,白马是一种马。
但是,我要证明,白马连“一种马”都不是!
=========== 我是严肃的分割线 ============
首先,要明确,什么是“白马”。我们可以定义:
[quote]定义:如果一匹马身上的毛都是白的,那么这匹马可以称为“白马“。[/quote]
姑且认为是全白的吧,也认为我们在生活中经常可以找到这样的马。类似的,我们可以定义“黑马”、“枣红马”等等。
对于任何一匹马,我们可以从这匹马上揪下一些毛。没问题吧。
对于任何一匹吗,我们可以给这匹马添加一些毛。假设我们可以这样做吧,加上一些毛仍然是那匹马。
随便拿一匹马(不管颜色),再拿一根黑毛,加在这匹马上,得到的仍然是马。
根据李氏替换原则,我们把这匹马换成一匹白马,我们也可以往上添加一些黑毛。
但是,我们不能给他添加黑毛,因为一旦添加了,得到的就不是白马了!
这不是有问题吗,凡是马都能往上边添加黑毛,白马是马,为什么给白马加上黑毛以后,就不是白马了呢?
——+——~~#¥+@%*¥(@ 我是华丽的分割线 @(¥*%@+¥#~~——+——
Java程序员可以这样编程序:
package baima;
import java.util.*;
class Fur {}
class BlackFur extends Fur {}
class WhiteFur extends Fur {}
interface Horse {
List<Fur> getFurs();
}
interface WhiteHorse extends Horse {
List<WhiteFur> getFurs();{ // ERROR: The return type is incompatible with Horse.getFurs()
}
可惜Java不允许你这样定义“白马“。Java认为,List<WhiteFur>不是List<Fur>的子类。
如果你了解Java的“协变类型”,你会想这样定义:
interface Horse {
List<? extends Fur> getFurs(); // OK
}
interface WhiteHorse extends Horse {
List<? extends WhiteFur> getFurs(); // OK
}
编译正确。
然后我们试试:
class ConcreteWhiteHorse implements WhiteHorse {
private List<WhiteFur> furs = new ArrayList<WhiteFur>();
@Override
public List<WhiteFur> getFurs() {
return furs;
}
}
public class BaimaTest {
public static void main(String[] args) {
WhiteHorse myHorse = new ConcreteWhiteHorse();
List<WhiteFur> furs = myHorse.getFurs(); // ERROR: Type mismatch: cannot convert from List<capture#1-of ? extends WhiteFur> to List<WhiteFur>
furs.add(new WhiteFur());
}
}
编译通不过。Java不允许从List<? extends WhiteFur>到List<WhiteFur>的转换。
如果我们这样:
public class BaimaTest {
public static void main(String[] args) {
WhiteHorse myHorse = new ConcreteWhiteHorse();
List<? extends WhiteFur> furs = myHorse.getFurs();
furs.add(new WhiteFur()); // ERROR: The method add(capture#2-of ? extends WhiteFur) in the type List<capture#2-of ? extends WhiteFur> is not applicable for the arguments (WhiteFur)
}
}
furs是List<? extends WhiteFur>型的,不能添加WhiteFur类型的元素。
看样子,不进行强制类型转换,总是会出错的。
我们这样呢?
public class BaimaTest {
public static void main(String[] args) {
WhiteHorse myHorse = new ConcreteWhiteHorse();
List<WhiteFur> furs = (List<WhiteFur>) myHorse.getFurs(); // WARNING: Unchecked
furs.add(new WhiteFur());
Horse myHorseAgain = myHorse;
List<Fur> fursAgain = (List<Fur>) myHorseAgain.getFurs(); // WARNING: Unchecked
fursAgain.add(new BlackFur());
for (WhiteFur wf : myHorse.getFurs()) { // java.lang.ClassCastException
System.out.println("This is a '"+wf.getClass().getSimpleName()+"'");
}
}
}
看样子没问题吧,编译也通过了。我们成功地给一只白马增加了一根黑毛。你在想,为什么不能呢?白马也是马,马可以加黑毛,白马为什么不能加黑毛呢?
for循环中,试图把myHorse.getFurs()中的成员赋给wf。这一行连警告都没有,因为编译器认为myHorse.getFurs()本来就是List<WhiteFur>型的,当然可以赋值给WhiteFur型的wf呀。
但是,运行时出错。第一根毛是白毛,没错。但是,第二根是黑毛,赋给wf时,类型转换失败。
[quote]
This is a 'WhiteFur'
Exception in thread "main" java.lang.ClassCastException: baima.BlackFur cannot be cast to baima.WhiteFur
at baima.BaimaTest.main(BaimaTest.java:41)
[/quote]
.......................我是无奈的分割线......................
好了,你说,白马到底是不是马呢?
参考:http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf