作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

我们之前使用类创造新的类型(type),并使用继承来便利我们创建类的过程。我将在这一讲中深入类型,并介绍多态(polymorphism)的概念。

类型检查

Java的任意变量和引用经过类型声明(type declaration),才能使用。我们之前见过对象数据、类数据、方法参数、方法返回值以及方法内部的自动变量,它们都需要声明其类型。Java是一种强类型(strongly typing)语言,它会对类型进行检查。如果我们错误的使用类型,将造成错误。

类型不符,卖萌无效

比如在下面的Test类中,我们将一个Cup类对象赋予给aPerson类引用:

public class Test
{
public static void main(String[] args)
{
Human aPerson;
aPerson = new Cup();
}
} class Human
{
/**
* constructor
*/
public Human(int h)
{
this.height = h;
} /**
* accessor
*/
public int getHeight()
{
return this.height;
} /**
* mutator
*/
public void growHeight(int h)
{
this.height = this.height + h;
} private int height;
} class Cup
{
public void addWater(int w)
{
this.water = this.water + w;
} public void drinkWater(int w)
{
this.water = this.water - w;
} private int water = 0;
}

javac将返回:

found   : Cup
required: Human
                aPerson = new Cup();             
                          ^
1 error

基本类型转换

Java可以对基本类型的变量进行类型转换。不同的基本类型有不同的长度和存储范围。如果我们从一个高精度类型转换到低精度类型,比如从float转换到int,那么我们有可能会损失信息。这样的转换叫做收缩变换(narrowing conversion)。这种情况下,我们需要显示的声明类型转换,比如:

public class Test
{
public static void main(String[] args)
{
int a;
a = (int) 1.23; // narrowing conversion
System.out.println(a);
}
}

如果我们从低精度类型转换成高精度类型,则不存在信息损失的顾虑。这样的变换叫做宽松变换(widening conversion)。我们不需要显示的要求类型转换,Java可以自动进行:

public class Test
{
public static void main(String[] args)
{
int a = 3;
double b;
b = a; // widening conversion
System.out.println(a);
}
}

基本类型转换

upcast与多态

在Java中,引用也可以进行类型转换,但是有限制。

我们可以将一个衍生类引用转换为其基类引用,这叫做向上转换(upcast)或者宽松转换。下面的BrokenCup类继承自Cup类,并覆盖了Cup类中原有的addWater()和drinkWater()方法:

 
public class Test
{
public static void main(String[] args)
{
Cup aCup;
BrokenCup aBrokenCup = new BrokenCup();
aCup = aBrokenCup; // upcast
aCup.addWater(10); // method binding
}
} class Cup
{
public void addWater(int w)
{
this.water = this.water + w;
} public void drinkWater(int w)
{
this.water = this.water - w;
} private int water = 0;
} class BrokenCup extends Cup
{
public void addWater(int w)
{
System.out.println("shit, broken cup");
} public void drinkWater(int w)
{
System.out.println("om...num..., no water inside");
}
}

程序运行结果:

shit, broken cup

在上面可以看到,不需要任何显示说明,我们将衍生类引用aBrokenCup赋予给它的基类引用aCup。类型转换将由Java自动进行。

我们随后调用了aCup(我们声明它为Cup类型)的addWater()方法。尽管aCup是Cup类型的引用,它实际上调用的是BrokenCup的addWater()方法!也就是说,即使我们经过upcast,将引用的类型宽松为其基类,Java依然能正确的识别对象本身的类型,并调用正确的方法。Java可以根据当前状况,识别对象的真实类型,这叫做多态(polymorphism)。多态是面向对象的一个重要方面。

多态是Java的支持的一种机制,同时也是面向对象的一个重要概念。这提出了一个分类学的问题,既子类对象实际上“是”父类对象。比如一只鸟,也是一个动物;一辆汽车,也必然是一个交通工具。Java告诉我们,一个衍生类对象可以当做一个基类对象使用,而Java会正确的处理这种情况。

比如下面的继承关系:

我们可以说用杯子(Cup)喝水(drinkWater)。实际上,喝水这个动作具体含义会在衍生类中发生很大变换。比如用吸管喝水,和从一个破杯子喝水,这两个动作差别会很大,虽然我们抽象中都讲“喝水”。我们当然可以针对每个衍生类分别编程,调用不同的drinkWater方法。然而,作为程序员,我们可以对杯子编程,调用Cup的drinkWater()方法,而无论这个杯子是什么样的衍生类杯子。Java会调用相应的正确方法,正如我们在上面程序中看到的。

看一个更加有意义的例子,我们给Human类增加一个drink()方法,这个方法接收一个杯子对象和一个整数作为参数。整数表示喝水的水量:

public class Test
{
public static void main(String[] args)
{
Human guest = new Human();
BrokenCup hisCup = new BrokenCup();
guest.drink(hisCup, 10);
}
} class Human
{
void drink(Cup aCup, int w)
{
aCup.drinkWater(w);
}
}

程序运行结果:

shit, no water inside

我们在Human类的drink()的定义中,要求第一个参量为Cup类型的引用。但在实际运用时(Test类),将Cup的BrokenCup衍生类对象。这实际上是将hisCup向上转型称为Cup类,传递给drink()方法。在方法中,我们调用了drinkWater()方法。Java发现这个对象实际上是BrokenCup对象,所以实际调用了BrokenCup的相应方法。

downcast

我们可以将一个基类引用向下转型(downcast)成为衍生类的引用,但要求该基类引用所指向的对象,已经是所要downcast的衍生类对象。比如可以将上面的hisCup向上转型为Cup类引用后,再向下转型成为BrokenCup类引用。

Object类型

Java中,所有的类实际上都有一个共同的继承祖先,即Object类。Object类提供了一些方法,比如toString()。我们可以在自己的类定义中覆盖这些方法。

Object: 祖先

我们可以编写一个操作Object对象的程序,就可以通过upcast,将任意对象传递给该程序。

我将在以后深入Object类。

(多态的实现是依靠RTTI的支持。我将在以后深入。)

总结

基本类型转换

polymorphism

downcast

Object

java Vamei快速教程12 类型转换和多态的更多相关文章

  1. java Vamei快速教程08 继承

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 继承(inheritance)是面向对象的重要概念.继承是除组合(composit ...

  2. java Vamei快速教程01

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Java是完全面向对象的语言.Java通过虚拟机的运行机制,实现“跨平台”的理念. ...

  3. java Vamei快速教程00

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Java是面向对象语言.这门语言其实相当年轻,于1995年才出现,由Sun公司出品 ...

  4. java Vamei快速教程16 RTTI

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 运行时类型识别(RTTI, Run-Time Type Identificatio ...

  5. java Vamei快速教程22 内存管理和垃圾回收

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 整个教程中已经不时的出现一些内存管理和垃圾回收的相关知识.这里进行一个小小的总结. ...

  6. java Vamei快速教程18 容器

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Java中有一些对象被称为容器(container).容器中可以包含多个对象,每个 ...

  7. java Vamei快速教程21 事件响应

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在GUI中,我们看到了如何用图形树来组织一个图形界面.然而,这样的图形界面是静态的 ...

  8. java Vamei快速教程20 GUI

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! GUI(Graphical User Interface)提供了图形化的界面,允许 ...

  9. java Vamei快速教程19 嵌套类

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 到现在为止,我们都是在Java文件中直接定义类.这样的类出现在包(package) ...

随机推荐

  1. Unity3D 脚本模板修改方法

    默认情况下,在Unity中创建C#脚本都会默认生成以下代码模板. using System.Collections; using System.Collections.Generic; using U ...

  2. MATLAB解决常微分方程

    首先得介绍一下,在matlab中解常微分方程有两种方法,一种是符号解法,另一种是数值解法.在本科阶段的微分数学题,基本上可以通过符号解法解决.   用matlab解决常微分问题的符号解法的关键命令是d ...

  3. git 修改远程仓库源

    自己已经写好了一个项目,想上传到 github github 创建新项目 新建 README.md , LICENSE 本地项目添加 github 远程仓库源 不是git项目 git remote a ...

  4. Docker容器构建过程的安全性分析

    来源:嘶吼专业版 ID:Pro4hou DevOps概念的流行跟近些年微服务架构的兴起有很大关系,DevOps是Dev(Development)和Ops(Operations)的结合,Dev负责开发, ...

  5. sql server 查询练习

    需要建的四个表: 学生表 create table Student ( Sno varchar(20) not null primary key, Sname varchar(20) not null ...

  6. ubuntu 14.04安装octave,及其使用

    从库安装: sudo apt-add-repository ppa:octave/stable sudo apt-get update sudo apt-get install octave 使用:以 ...

  7. kvm磁盘io优化以及性能测试以及与物理机对比

    ubuntu下kvm的磁盘io性能优化步骤 1.virsh shutdown wcltest2 2.virsh edit wcltest2 <driver name='qemu' type='q ...

  8. 省选九省联考T2 IIIDX(线段树)

    题目传送门:https://www.luogu.org/problemnew/show/P4364 期中考后记:期中考刚考完,感觉不咋滴,年排第3.我抗压力太差了..期末得把rank1抢回来. 本来感 ...

  9. 1160: sundari && Shortest path HDU - 4479

    http://gdutcode.sinaapp.com/problem.php?id=1160 http://acm.hdu.edu.cn/showproblem.php?pid=4479 35 51 ...

  10. JavaFX常用汇总

    1. 描述备注 1.1 参考教程 博客 易百教程 JavaFX中国 1.5 安装 a). 在线安装e(fx)clipse插件 b). 下载安装SceneBuilder c). eclipse重启以后, ...