继承与多态

  • 1.为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来?

答:由于子类是继承父类的,所以想用子类创建对象时,必须先创建父类的对象,这样子类才能有父类的属性和方法。在创建对象时如果父类的数据需要进行初始化,那么就需要调用父类的构造函数。不能反过来,因为父类不知道子类有什么属性,而且反过来子类也不能得到父类初始化的变量。

2.参看ExplorationJDKSource.java示例

此示例中定义了一个类A,它没有任何成员:

class A { }

示例直接输出这个类所创建的对象

       public static void main(String[] args)    {

              System.out.println(new A());

}

我们得到了一个奇特的运行结果:

         A@1c5f743版)

为什么?

答:函数实际上是继承了Object类中的toString方法,因此会有结果输出。

  • 3.动手动脑:请自行编写代码测试以下特性:
    • 在子类中,若要调用父类中被覆盖的方法,可以使用super关键字。

答:源代码:

//信1603班    20163514  周志慧

package test1_3;

class Fruit1

{

   public void show()

   {

   System.out.println("Fruit");

   }

}

class Fruit2 extends Fruit1

{

  

   public void show()

   {

      super.show();

      System.out.println("Pear");

     

   }

  

}

public class Test {

 

   public static void main(String[] args) {

      // TODO 自动生成的方法存根

       Fruit2 f=new Fruit2();

       f.show();

            

 

   }

 

}

  • 4.现在有三个类:

class Mammal{}

class Dog extends Mammal {}

class Cat extends Mammal{}

  • 针对每个类定义三个变量并进行初始化

       Mammal m=null ;

       Dog d=new Dog();

       Cat c=new Cat();

 

下列语句哪一个将引起编译错误?为什么?哪一个会引起运行时错误?为什么?

                   m=d;

                   d=m;

                   d=(Dog)m;

                   d=c;

                   c=(Cat)m;

答:第二句,第四句会出现运行错误。

   由于Dog和Cat都是继承的Mammal类,Mammal类是Dog类和Cat类的父类,由于基类对象要赋值给子类必须进行强制类型转换,因此第二句会运行错误;两个子类的类型也不一样因此也不能进行赋值语句。

  • 5.运行以下测试代码

回答问题:

1.   左边的程序运行结果是什么?

2.   你如何解释会得到这样的输出?

3.   计算机是不会出错的,之所以得

            到这样的运行结果也是有原因的,

            那么从这些运行结果中,你能总

            结出Java的哪些语法特性?

答:1.运行结果:

Parent.printValue(),myValue=100

Child.printValue(),myValue=200

Child.printValue(),myValue=200

Child.printValue(),myValue=200

Child.printValue(),myValue=201

2.

运行结果解释:

Parent类中myValue值为100;Child类中myValue值为200;

因此第一句Parent parent=new Parent();是创建了Parent类的对象parent

      parent.printValue();对象parent调用了printValue函数,由于Parent类中myValue值为100,因此此时myValue值为100;

第二句Child child=new Child();创建了Child的对象child

      child.printValue();对象parent调用了printValue函数,由于Child类中myValue值为200,因此此时myValue值为200;

第三局parent=child;是将子类child赋值给基类parent

      parent.printValue();调用的是Child类中的printValue函数,Child类中的myValue值为200,因此此时输出值为200;

第四句parent.myValue++;parent中已经被child赋值,执行myValue++;

      parent.printValue();由于在第三句中已经将对象child赋值给parent因此此时的操作应该是对于child对象的操作,执行myValue++后myValue值并没有改变,因此输出值为200;

第五句((Child)parent).myValue++;将对象parent进行强制性转换为Child类,执行的为parent对象的操作;此时myValue值为201;

      parent.printValue();执行myValue++后myValue值依旧为201;

  • 6.请使用javap查看编译器为TestPolymorphism.java生成的字节码指令,然后通过互联网搜索资料,尝试从底层开始理解Java编译器是如何为多态代码生成字节码指令,在程序运行过程中,多态特性又是如何实现的。

答: 在 java 语言中,多态性体现在两个方面:由方法重载实现的静态多态性(编译时多态)和方法重写实现的动态多态性(运行时多态)。

  (1)编译时多态

    在编译阶段,具体调用哪个被重载的方法,编译器会根据参数的不同来静态确定调用相应的方法。  

  (2)运行时多态

    由于子类继承了父类所有的属性(私有的除外),所以子类对象可以作为父类对象使用。程序

    中凡是使用父类对象的地方,都可以用子类对象来代替。一个对象可以通过引用子类的实例来调用
    子类的方法。

    重写方法的调用原则(为重点):java 运行时系统根据调用该方法的实例,来决定调用哪个方法。

    对子类的一个实例,如果子类重写了父类的方法,则运行时系统调用子类的方法;如果子类继承了
    父类的方法(未重写),则运行时系统调用父类的方法。

原文地址:https://www.cnblogs.com/zzh2019979439/p/7810758.html