Java基础12 类型转换与多态

我们之前使用类创造新的类型(type),并使用继承来便利我们创建类的过程。

我将在这一讲中深入类型。并介绍多态(polymorphism)的概念。

 出处:http://www.cnblogs.com/vamei

类型检查

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


posted on 2017-08-13 15:55  yutingliuyl  阅读(160)  评论(0编辑  收藏  举报