`
cloverprince
  • 浏览: 126874 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

证明:白马非马

阅读更多
公孙龙说:“白马非马”。

当然,这可以理解成,“白马“和“马“不是全同的概念,白马是一种马。

但是,我要证明,白马连“一种马”都不是!

=========== 我是严肃的分割线 ============

首先,要明确,什么是“白马”。我们可以定义:

引用
定义:如果一匹马身上的毛都是白的,那么这匹马可以称为“白马“。


姑且认为是全白的吧,也认为我们在生活中经常可以找到这样的马。类似的,我们可以定义“黑马”、“枣红马”等等。

对于任何一匹马,我们可以从这匹马上揪下一些毛。没问题吧。

对于任何一匹吗,我们可以给这匹马添加一些毛。假设我们可以这样做吧,加上一些毛仍然是那匹马。

随便拿一匹马(不管颜色),再拿一根黑毛,加在这匹马上,得到的仍然是马。

根据李氏替换原则,我们把这匹马换成一匹白马,我们也可以往上添加一些黑毛。

但是,我们不能给他添加黑毛,因为一旦添加了,得到的就不是白马了!

这不是有问题吗,凡是马都能往上边添加黑毛,白马是马,为什么给白马加上黑毛以后,就不是白马了呢?


——+——~~#¥+@%*¥(@  我是华丽的分割线 @(¥*%@+¥#~~——+——


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时,类型转换失败。

引用

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)


.......................我是无奈的分割线......................

好了,你说,白马到底是不是马呢?

参考:http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

1
2
分享到:
评论

相关推荐

    2018年考研政治真题试题及答案(完整版)1

    1.马克思主义的产生具有深刻的社会根源、阶级基础和思想渊源,其创始人马克思 2.“ 马者所以命形也:白者所以命色也,命色者非命形也,故曰白马非马 3.坚持以人民

    远征者3g建站系统V3.8完整版

    本系统为本人(白马非马)历经两年,集众多程序之所长,精心编写而成。这套程序,可谓倾尽白马无数心血,也见证着白马从一个菜鸟到学会编程的历程(不敢妄称高手),其中辛酸,不足为外人道也,希望使用此程序的站长好好珍惜。 ...

    数据结构-栈和队列-停车场管理问题

    数据结构栈与队列专题,停车场管理问题。 原题如下: 设停车场是一个可停放n辆汽车的狭长通道,且只有一个大门可供汽车进出。汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的...

    自动指纹识别技术

    从图像基本概念入手,介绍自动指纹识别技术,简单易懂

    TortoiseGit 64bit

    CSDN拥有自己的CODE版本控制平台,完美兼容git的操作,非常适合我们托管自己的项目。这里推荐工具TortoiseGit作为操作的工具。 具体操作:https://code.csdn.net/help/CSDN_Code/code_support/new_3

    64bit ft232usbuart驱动

    64位机专用的ft232usbuart驱动:正确安装驱动后Tera Term 等工具才能正确使用,获得串口的log信息。

    student infomation

    我的博文 "Windows下MySQL学习(三):让MySQL数据库支持中文,Matlab导入excel表到数据库" ,用到的测试文件

    椭圆和五角星的源代码

    椭圆和五角星的源代码, 非常适合C++初学者...

    软件班_李贵荣_实验一.rar

    软件班_李贵荣_实验一.rar

    MNIST1.rar

    这个压缩包里面包含了mnist数据集的压缩包和调用,显示其数据的代码。能够方便地实现神经网络通过前向传播对手写数据集识别精度的测定,里面的代码配有我自己的注解,方便大家的阅读。

    HTML入门标签

    比较详细的HTML标签,常用到的标签都包括在内了。新手可以看看

    Linux入门学习笔记

    初步学习Linux的学习经验,对于刚开始学习Linux系统的同学来说,是一份很好的资源

    Redis入门基础学习笔记

    Redis入门基础学习笔记

    CSS入门讲解

    WEB项目第二天,HTML和CSS入门讲解,内容还是比较详细的

    JavaWEB阶段课程体系结构

    整个JAVA WEB的学习方向,从简及深。前端,数据库,服务器

    苹果(Authentec)指纹识别技术PPT

    苹果(Authentic)指纹识别技术原理介绍,非常详细,公开

    自动指纹识别系统课件

    超详细64页PPT,全面介绍自动指纹识别系统的工作原理

    WEB03_JavaScript入门

    WEB项目第三天,JavaScript入门讲解,内容还算比较详细。

    酷炫网站后台框架(40个)

    自己整理的40个酷炫网站后台框架,供有需要的人使用。

    达普 热敏打印机EH300 使用手册和测试apk

    以市面上常见的达普 热敏打印机EH300为例,提供android系统外设开发所需的使用手册和测试apk,实测,可用USB控制打印。如有问题,请查看本人相关博文。

Global site tag (gtag.js) - Google Analytics