Java基础教程之类型转换与多态

我们之前使用类创造新的类型(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

(0)

相关推荐

  • JAVA中string数据类型转换详解

    在JAVA中string是final类,提供字符串不可以修改,string类型在项目中经常使用,下面给大家介绍比较常用的string数据类型转换: String数据类型转换成long.int.double.float.boolean.char等七种数据类型 复制代码 代码如下: * 数据类型转换 * @author Administrator * */ public class 数据类型转换 { public static void main(String[] args) { String c=

  • java的各种类型转换全部汇总(推荐)

    java类型转换 Integer String Long Float Double Date 1如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或 i = Integer.parseInt([String],[int radix]); 2). int i = Integer.valueOf(my_str).intValue(); 注: 字串转成 Double, Float, Long 的方法大同小

  • 浅析Java中对象的创建与对象的数据类型转换

    Java:对象创建和初始化过程 1.Java中的数据类型     Java中有3个数据类型:基本数据类型(在Java中,boolean.byte.short.int.long.char.float.double这八种是基本数据类型).引用类型和null类型.其中,引用类型包括类类型(含数组).接口类型.     下列语句声明了一些变量: int k ; A a; //a是A数据类型的对象变量名. B b1,b2,-,b10000;// 假定B是抽象类或接口. String s; 注意:从数据类型

  • Java中常用的类型转换(推荐)

    1.将字符串转换成整数(String--->int) 方法一: (1) int i = Integer.parseInt(String s); 其中(1)其实就是我们经常用到的将s转换为10进制得数,其实默认是调用了 int i =Integer.parseInt("123",10); (2) i = Integer.parseInt(String s,int radix); radix的范围是在2~36之间,超出范围会抛异常.其中s的长度也不能超出7,否则也会抛异常. 方法二:

  • 详解Java多态对象的类型转换与动态绑定

    Java多态对象的类型转换 这里所说的对象类型转换,是指存在继承关系的对象,不是任意类型的对象.当对不存在继承关系的对象进行强制类型转换时,java 运行时将抛出 java.lang.ClassCastException 异常. 在继承链中,我们将子类向父类转换称为"向上转型",将父类向子类转换称为"向下转型". 很多时候,我们会将变量定义为父类的类型,却引用子类的对象,这个过程就是向上转型.程序运行时通过动态绑定来实现对子类方法的调用,也就是多态性. 然而有些时候

  • 浅谈Java中强制类型转换的问题

    为了更好的理解我们先看下面的例子: package com.yonyou.test; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * 测试类 * @author 我们 * @创建日期 2016-5-31 */ public class Test{ public static void main(String[] args) { List<String> list=new Ar

  • Java数据类型转换详解

    一.基本数据类型阐述 Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型. [注]JAVA没有unsigned类型 (1). 整数:int,short,byte,long (2). 浮点型:float,double (3). 字符:char (4). 布尔:boolean 基本型别     大小         最小值            最大值 void boolean     -----         -----             

  • Java基础教程之类型转换与多态

    我们之前使用类创造新的类型(type),并使用继承来便利我们创建类的过程.我将在这一讲中深入类型,并介绍多态(polymorphism)的概念.  类型检查 Java的任意变量和引用经过类型声明(type declaration),才能使用.我们之前见过对象数据.类数据.方法参数.方法返回值以及方法内部的自动变量,它们都需要声明其类型.Java是一种强类型(strongly typing)语言,它会对类型进行检查.如果我们错误的使用类型,将造成错误. 类型不符,卖萌无效 比如在下面的Test类中

  • Java基础之方法重写和多态示例

    本文实例讲述了Java基础之方法重写和多态.分享给大家供大家参考,具体如下: 示例代码: 子类的方法与父类的方法具有相同的返回类型和签名,子类方法重写父类方法. class A{ int i,j; //父类变量 A(int a,int b){ //父类构造 i=a; j=b; } void show(){ //父类方法 System.out.println(i+" "+j); } } class B extends A{ //继承父类 int k; //子类变量 B(int a,int

  • Java基础教程_判断语句if else

    与三元运算符相比: 好处:可以简化if else 代码 弊端 因为是一个运算符,所以运算玩必须要有一个结果 以上这篇Java基础教程_判断语句if else就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • Java基础之面向对象机制(多态、继承)底层实现

    一.Java的前世 为什么会产生Java?Java的特点是什么? 从C语言开始讲,C语言是一种结构化语言,模块化编程,便于程序的调试,依靠非常全面的运算符和多样的数据类型,可以轻易完成各种数据结构的构建,通过指针类型更可对内存直接寻址以及对硬件进行直接操作,因此既能够用于开发系统程序,也可用于开发应用软件.其缺点就是封装性弱,程序的安全性上不是很好.C语言的异常处理一般使用setjmp()与longjmp(),在捕获到异常时进行跳转:或者使用abort()和exit()两个函数,强行终止程序的运

  • Java基础教程之数组的定义与使用

    目录 一.数组的基本概念 二.数组的声明 三.数组的创建及初始化 1.数组的创建 2.数组的初始化 四.访问数组元素 五.for each 循环 六.数组的拷贝 七.数组排序 八.二维数组 总结 一.数组的基本概念 数组是一种数据类型,用来存储同一类型值的集合,它在内存中是一段连续的空间.通过一个整形下标(index,或者称之为索引)可以访问数组中的每一个值.例如,如果a是一个整型数组,a[i]就是一个下标为i的一个整数,数组是一种引用类型. 二.数组的声明 声明数组变量时,需要指出数组类型(数

  • Java基础教程之获取操作系统及浏览器信息

    目录 User Agent 的含义 浏览器的 UA 字串 UserAgentUtils.jar 通过(User-Agent)获取 浏览器类型,操作系统类型,手机机型 再给出一个: 总结 在生产环境下,我们需要关闭swagger配置,避免暴露接口的这种危险行为. User Agent 的含义 User Agent 中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本.CPU 类型.浏览器及版本.浏览器渲染引擎.浏览器语言.浏览器插件等. 一些网站常常通过判

  • java基础教程之拼图游戏的实现

    目录 前言 废话不多说,直接上效果图: 1.所需技术 2.具体实现 2.1 图片制作 2.2 创建项目 2.3 编码实现 总结 前言 大家在初学java的时候,大部分的代码都是在控制台上运行的.可能大家辛辛苦苦写了几十行代码,最终就只是在控制台输出一个字符,这个时候,心里肯定是拔凉拔凉的,心中那一朵编程的火花,就马上给扑灭了.我们都知道兴趣是最好的老师.为了拯救大家快要熄灭的小火花,小编在这里给大家带来使用java做个小游戏,并且通过做这个游戏,好好收悉一下面向对象的实际使用. 废话不多说,直接

  • Java基础教程之整数运算

    目录 引言 溢出 自增/自减 移位运算 位运算 运算优先级 类型的自动提升与强制转型 练习 小结 总结 引言 Java的整数运算遵循四则运算规则,可以使用任意嵌套的小括号.四则运算规则和初等数学一致.例如: public class Main { public static void main(String[] args) { int i=(100+200)*(99-88);//3300 int n=7*(5+(i-9));//23072 System.out.println(i); Syste

  • Java基础教程之理解Annotation详细介绍

    Java基础之理解Annotation 一.概念  Annontation是Java5开始引入的新特征.中文名称一般叫注解.它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类.方法.成员变量等)进行关联. 更通俗的意思是为程序的元素(类.方法.成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且是供指定的工具或框架使用的. Annontation像一种修饰符一样,应用于包.类型.构造方法.方法.成员变量.参数及本地变量的声明语句中.

  • Java基础教程之对象的方法与数据成员

    在Java基础教程之从Hello World到面向对象一文中,我们初步了解了对象(object).对象中的数据成员表示对象的状态.对象可以执行方法,表示特定的动作. 此外,我们还了解了类(class).同一类的对象属于相同的类型(type).我们可以定义类,并使用该定义来产生对象. 我们进一步深入到对象.了解Java中方法与数据成员的一些细节. 调用同一对象的数据成员 方法可以调用该对象的数据成员.比如下面我们给Human类增加一个getHeight()的方法.该方法返回height数据成员的值

随机推荐