一、今日学习内容:

动手动脑:

1、继承条件下的构造方法调用

运行TestInherits.java示例,观察输出,注意总结父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent的另一个构造函数,注意这句调用代码是否是第一句,影响重大!

TestInherits.java

class Grandparent {

 

    public Grandparent() {

        System.out.println("GrandParent Created.");

    }

 

    public Grandparent(String string) {

        System.out.println("GrandParent Created.String:" + string);

    }

}

 

class Parent extends Grandparent {

 

    public Parent() {

        //super("Hello.Grandparent.");

        System.out.println("Parent Created");

       // super("Hello.Grandparent.");

    }

}

 

class Child extends Parent {

 

    public Child() {

        System.out.println("Child Created");

    }

}

 

public class TestInherits {

 

    public static void main(String args[]) {

        Child c = new Child();

    }

}

实验结果截图:

 

结论: 通过 super 调用基类构造方法,必须是子类构造方法中的第一个语句。

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

构造函数的主要作用:构造函数是类的一个特殊方法,这个方法用来生成实例时由系统自动调用,程序员无法直接调用。构造函数方法名同类名相同且参数为空。子类继承父类后默认继承父类的构造函数,即:子类存在隐含方法:super(),如果子类重写构造函数则子类也隐含调用super()

3、“方法覆盖(override)”的要点

(1)方法覆盖要求子类与父类的方法一模一样,否则就是方法重载(overload)!

(2)请自行编写代码测试以下特性(动手动脑):

  • 在子类中,若要调用父类中被覆盖的方法,可以使用super关键字。

4、实验代码:TestInherit.java

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

class Father

{

       public void multiplication(double a,double b)

       {

              System.out.println("父类的函数:"+a+"*"+b+"="+a*b);

       }

}

 

class Me extends Father

{

       public void multiplication(double a,double b)

       {

              super.multiplication(a+1, b+2);

              System.out.println("父类的函数:"+a+"*"+b+"="+a*b);

 

       }

}

 

public class TestInherit

{

       public static void main(String[] args)

       {

              Me a=new Me();

              a.multiplication(1,1.2);

       }

}

结果截图:

 

5、

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

    

          程序结果:

  

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

  前两个都是parent和child分别调用的自己方法,输出自己的值。第三个parent引用子类child类的对象则调用child的方法。第四个是parent里面的Value加一,但是child里面的Value并没有加1还是调用child的方法,值不会变。第五个进行了类型转换,结果是child里面的Value+1输出结果为201。

(3)计算机是不会出错的,之所以得 到这样的运行结果也是有原因的,那么从这些运行结果中,你能总结出Java的哪些语法特性?

  总结:当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。如果子类被当作父类使用,则通过子类访问的字段是父类的。

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

class parent       

{
      public int value=100;

    public void Introduce()

         {
          System.out.println("I'm father");

         }

}

 

 class Son extends parent

{
      public int value=101;

         public void Introduce()

      {
              System.out.println("I'm son");  

}

 

}

 

 

class Daughter extends parent

{
      public int value=102;

      public void Introduce()

      {
           System.out.println("I'm daughter");

}

}

 

public class TestPolymorphism

{
    public static void main(String args[])

    {
        parent p=new parent();

        p.Introduce();

         System.out.println(p.value); 

        p=new Son(); 

        p.Introduce(); 

        System.out.println(p.value);

        p=new Daughter(); 

        p.Introduce();

        System.out.println(p.value);

       }  

}

结果截图:

            

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

  (1)编译时多态

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

  (2)运行时多态

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

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

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

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

7、思索: 这种编程方式有什么不合理的地方吗?

public class Zoo 
{

    public static void main(String args[])
    {

        Feeder f = new Feeder("小李");

        // 饲养员小李喂养一只狮子

        f.feedLion(new Lion());

        // 饲养员小李喂养十只猴子

        for (int i = 0; i < 10; i++)
         {

            f.feedMonkey(new Monkey());

        }
        
        // 饲养员小李喂养5只鸽子

        for (int i = 0; i < 5; i++)
         {

            f.feedPigeon(new Pigeon());

        }
    
    }

}


class Feeder 
{


    public String name;


    public Feeder(String name)
    {

        this.name = name;

    }

    
    public void feedLion(Lion l)
    {

        l.eat();

    }

    
    public void feedPigeon(Pigeon p)
    {

        p.eat();

    }

    
    public void feedMonkey(Monkey m)
    {

        m.eat();

    }

}


class Lion
{


    public void eat() 
    {

        System.out.println("我不吃肉谁敢吃肉!");

    }

}


class Monkey 
{

    public void eat() 
    {

        System.out.println("我什么都吃,尤其喜欢香蕉。");

    }

}


class Pigeon 
{


    public void eat() 
    {

        System.out.println("我要减肥,所以每天只吃一点大米。");

    }

}

 

zoo2.java

public class Zoo 
{

    
    public static void main(String args[])
    {

            Feeder f = new Feeder("小李");

            //饲养员小李喂养一只狮子

            f.feedAnimal(new Lion());
            //饲养员小李喂养十只猴子

            for (int i = 0; i < 10; i++) 
        {

                f.feedAnimal(new Monkey());
    
        }

            //饲养员小李喂养5只鸽子

            for (int i = 0; i < 5; i++) 
        {

                f.feedAnimal(new Pigeon());

            }

    }

}


class Feeder 
{


    public String name;


    Feeder(String name) 
    {

        this.name = name;

    }

    
    public void feedAnimal(Animal an) 
   {

        an.eat();

    }

}


abstract class Animal 
{


    public abstract void eat();

}


class Lion extends Animal 
{


    public void eat() 
   {

        System.out.println("我不吃肉谁敢吃肉!");

    }

}


class Monkey extends Animal 
{


    public void eat() 
    {

        System.out.println("我什么都吃,尤其喜欢香蕉。");

    }

}


class Pigeon extends Animal 
{

    
    public void eat() 
    {

        System.out.println("我要减肥,所以每天只吃一点大米。");

    }

}

zoo3.java

package zoo3;


public class Zoo {

    public static void main(String args[]) {
        Feeder f = new Feeder("小李");
        Animal[] ans = new Animal[16];

        //饲养员小李喂养一只狮子
        ans[0] = new Lion();
        //饲养员小李喂养十只猴子
        for (int i = 0; i < 10; i++) {
            ans[1 + i] = new Monkey();
        }
        //饲养员小李喂养5只鸽子
        for (int i = 0; i < 5; i++) {
            ans[11 + i] = new Pigeon();
        }

        f.feedAnimals(ans);
    }
}

class Feeder {

    public String name;

    Feeder(String name) {
        this.name = name;
    }

    public void feedAnimals(Animal[] ans) {
        for (Animal an : ans) {
            an.eat();
        }
    }
}

abstract class Animal {

    public abstract void eat();
}

class Lion extends Animal {

    public void eat() {
        System.out.println("我不吃肉谁敢吃肉!");
    }
}

class Monkey extends Animal {

    public void eat() {
        System.out.println("我什么都吃,尤其喜欢香蕉。");
    }
}

class Pigeon extends Animal {

    public void eat() {
        System.out.println("我要减肥,所以每天只吃一点大米。");
    }
}

zoo4.java

import java.util.Vector;

public class Zoo {

    public static void main(String args[]) {
        Feeder f = new Feeder("小李");
        Vector<Animal> ans = new Vector<Animal>();

        //饲养员小李喂养一只狮子
        ans.add(new Lion());
        //饲养员小李喂养十只猴子
        for (int i = 0; i < 10; i++) {
            ans.add(new Monkey());
        }
        //饲养员小李喂养5只鸽子
        for (int i = 0; i < 5; i++) {
            ans.add(new Pigeon());
        }
        f.feedAnimals(ans);
    }
}

class Feeder {

    public String name;

    Feeder(String name) {
        this.name = name;
    }

    public void feedAnimals(Vector<Animal> ans) {
        for (Animal an : ans) {
            an.eat();
        }
    }
}

abstract class Animal {

    public abstract void eat();
}

class Lion extends Animal {

    public void eat() {
        System.out.println("我不吃肉谁敢吃肉!");
    }
}

class Monkey extends Animal {

    public void eat() {
        System.out.println("我什么都吃,尤其喜欢香蕉。");
    }
}

class Pigeon extends Animal {

    public void eat() {
        System.out.println("我要减肥,所以每天只吃一点大米。");
    }
}

 

 

posted on 2020-10-22 15:55  白日梦想家~  阅读(50)  评论(0编辑  收藏  举报