java之多态性

来源:互联网 发布:手机ps软件 编辑:程序博客网 时间:2024/06/15 13:22

4.8 多态

    定义:某一类事物的多种存在形态。
    

    例:动物中猫,狗。
    猫这个对象对应的类型是猫类型:猫 x = new 猫();
    同时猫也是动物中的一种,也可以把猫称为动物:动物  y = new 猫();
    动物是猫和狗具体事物中抽取出来的父类型。
    父类型引用指向了子类对象。

    多态性简单说就是一个对象对应着不同类型。

    体现:
    父类或者接口的引用指向或者接收自己的子类对象。

    作用:
    多态的存在提高了程序的扩展性和后期可维护性。

    
    前提:
    1. 需要存在继承或者实现关系。
    2. 需要有覆盖操作。

    
    好处:
    提高了代码的扩展性,前期定义的代码可以使用后期的内容。
    弊端:
    前期定义的内容不能使用(调用)后期子类的特有内容。


    示例1:
  1. abstract class Animal{
  2.        abstract void eat();
  3. }

  4. class Dog extends Animal{
  5.        void eat(){
  6.             System.out.println("啃骨头");
  7.        }
  8.        void lookHome(){
  9.             System.out.println("看家");
  10.        }
  11. }

  12. class Cat extends Animal{
  13.        void eat(){
  14.             System.out.println("吃鱼");
  15.        }
  16.        void catchMouse(){
  17.             System.out.println("抓老鼠");
  18.        }
  19. }

  20. class Pig extends Animal{
  21.        void eat(){
  22.             System.out.println("饲料");
  23.        }
  24.        void gongdi(){
  25.             System.out.println("拱地");
  26.        }
  27. }

  28. class DuoTaiDemo{
  29.        public static void main(String[] args){
  30.             Cat c = new Cat();
  31.             Dog d = new Dog();

  32.              method(c);
  33.              method(d);
  34.              method(new Pig());
  35.        }

  36.        public static void method(Animal a){
  37.             a.eat();
  38.        }
  39. }

   运行结果:


    示例2:
  1. class DuoTaiDemo{
  2.      public static void main(String[] args){
  3.           //自动类型提升,猫对象提升到了动物类型。但是特有功能无法访问,作用就是限制对特有功能的访问。
  4.           //专业讲:向上转型,将子类型隐藏。就不能使用子类的特有方法了。
  5.           Animal a = new Cat();
  6.           a.eat();
  7.           //a.catchMouse();//报错

  8.           //如果还想用具体动物猫的特有功能。
  9.           //你可以将该对象进行向下转型。
  10.           Cat c = (Cat)a; //向下转型的目的是为了能够使用子类中的特有方法。
  11.           c.eat();
  12.           c.catchMouse();

  13.           //注意:对于转型,自始至终都是子类对象在做类型的变化。
  14.           //Animal a = new Dog();
  15.           //Cat c = (Cat)a;//但是类型不能随意转换,否则可能会报出ClassCastException的异常
  16.      }

  17.      public static void method(Animal a){
  18.           a.eat();
  19.      }
  20. }

    运行结果:


    P.S.
    instanceof :用于判断对象的具体类型,只能用于引用数据类型判断,通常在向下转型前用于健壮性的判断。

    示例4:
  1. class DuoTaiDemo{
  2.        public static void main(String[] args){
  3.        }

  4.        public static void method(Animal a){
  5.             a.eat();
  6.             
  7.              if(a instanceof Cat){ 
  8.                   Cat c = (Cat )a;
  9.                   c.catchMouse();
  10.              }
  11.              else if (a instanceof Dog){
  12.                   Dog d = (Dog )a;
  13.                   d.lookHome();
  14.              }
  15.        }
  16. }

    
    多态时,成员的特点:
    1. 成员变量
       编译时:参考引用型变量所属的类中是否有调用的成员变量。有,编译通过,没有,编译失败。
       运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。
       简单说:编译和运行都参考等号的左边。


    示例:
  1. class Fu{
  2.        int num = 3;
  3. }

  4. class Zi extends Fu{
  5.        int num = 4;
  6. }

  7. class DuoTaiDemo{
  8.        public static void main(String[] args){
  9.             Zi f1 = new Zi();
  10.             System.out.println(f1.num);
  11.             Fu f2 = new Zi();
  12.             System.out.println(f2.num);
  13.        }
  14. }

   运行结果:


    2. 成员函数(非静态)
       编译时:参考引用型变量所属的类中是否有调用的函数。有,编译通过。没有,编译失败。
       运行时:参考的是对象所属的类中是否有调用的函数。
       简单说:编译看左边,运行看右边。


    示例:
  1. class Fu{
  2.        void show(){
  3.             System.out.println("fu show");
  4.        }
  5. }

  6. class Zi extends Fu{
  7.        void show(){
  8.             System.out.println("zi show");
  9.        }
  10. }

  11. class DuoTaiDemo{
  12.        public static void main(String[] args){
  13.             Fu f = new Zi();
  14.             f.show();
  15.        }
  16. }

    运行结果:

 

    3. 静态函数
       编译时:参考的是对象所属的类中是否有调用的函数。
       运行时:参考的是对象所属的类中是否有调用的函数。
       简单说:编译和运行看左边。

    示例:
  1. class Fu{
  2.        static void method(){
  3.             System.out.println("fu static method");
  4.        }
  5. }

  6. class Zi extends Fu{
  7.        static void method(){
  8.             System.out.println("zi static method");
  9.        }
  10. }

  11. class DuoTaiDemo{
  12.        public static void main(String[] args){
  13.             Fu f = new Zi();
  14.             f.method();// fu static method
  15.             Fu.method();
  16.        }
  17. }

   运行结果:


    4.9 内部类

    定义:
    将一个类定义在另一个类的里面,里面那个类就称为内部类(内置类,嵌套类)。

    访问特点:
    内部类可以直接访问外部类中的成员,包括私有成员。
    而外部类要访问内部类中的成员必须要建立内部类的对象。

    示例1:
  1. /*
  2. 内部类的设计:
  3. 分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被描述事物的内容,这时候就定义内部类。
  4. */
  5. class Outer{
  6.        private int num = 3;

  7.        class Inner //内部类
  8.        {
  9.              void show(){
  10.                   System.out.println("show run..." + num);
  11.              }
  12.        }

  13.        public void method(){
  14.             Inner in = new Inner();
  15.             in.show();
  16.        }
  17. }

  18. class InnerClassDemo{
  19.        public static void main(String[] args){
  20.             Outer out = new Outer();
  21.             out.method();
  22.        }
  23. }

   运行结果:


    示例2:  
  1. class Outer{
  2.        private int num = 3;

  3.        class Inner
  4.        {
  5.              void show(){
  6.                   System.out.println("show run..." + num);
  7.              }
  8.        }
  9. }

  10. class InnerClassDemo{
  11.        public static void main(String[] args){
  12.              //直接访问外部类中的内部类中的成员
  13.             Outer.Inner in = new Outer().new Inner();
  14.             in.show();
  15.        }
  16. }

   运行结果:


    内部类的位置:
    内部类定义在成员位置上,可以被private、static成员修饰符修饰。被static修饰的内部类只能访问外部类中的静态成员。

    示例1:

  1. class Outer{
  2.        private static int num = 3;

  3.        static class Inner
  4.        {
  5.              void show(){
  6.                   System.out.println("show run..." + num);
  7.              }
  8.        }
  9. }

  10. class InnerClassDemo{
  11.        public static void main(String[] args){
  12.              //如果内部类是静态的,相当于一个外部类
  13.             Outer.Inner in = new Outer.Inner();
  14.             in.show();
  15.        }
  16. }

    运行结果:

 

    示例2:如果内部类是静态的,内部类成员也是静态的,可以不用创建内部类对象,直接调用。
  1. class Outer{
  2.        private static int num = 3;

  3.        static class Inner
  4.        {
  5.              static void show(){
  6.                   System.out.println("show run..." + num);
  7.              }
  8.        }
  9. }

  10. class InnerClassDemo{
  11.        public static void main(String[] args){
  12.             Outer.Inner.show();
  13.        }
  14. }

   运行结果:


    P.S.        
    1、如果内部类中定义了静态成员,该内部类也必须是静态的!

    示例:
  1. class Outer{
  2.      private static int num = 3;

  3.      static class Inner
  4.      {
  5.           static void show(){
  6.                System.out.println("show run..." + num);
  7.           }
  8.      }
  9. }


    2、为什么内部类能直接访问外部类中的成员呢?
         那是因为内部类持有了外部类的引用,外部类名.this。  

    示例:
  1. class Outer{
  2.        int num = 3;
  3.        class Inner{
  4.              int num = 4;
  5.              void show(){
  6.                    int num = 5;
  7.                    System.out.println(num);
  8.                    System.out.println(this.num);
  9.                    System.out.println(Outer.this.num);
  10.              }
  11.        }
  12.        void method(){
  13.              new Inner().show();
  14.        }
  15. }

  16. class InnerClassDemo{
  17.        public static void main(String[] args){
  18.              new Outer().method();
  19.        }
  20. }

    运行结果:


    3、内部类定义在局部位置上,也可以直接访问外部类中的成员。
         同时可以访问所在局部中的局部变量,但必须是被final修饰的。

    示例:
  1. class Outer{
  2.        int num = 3;
  3.        void method(final int y){
  4.              final int x = 9;
  5.              class Inner{
  6.                    void show(){
  7.                         System.out.println("show..." + x + "," + y);
  8.                    }
  9.              }
  10.             Inner in = new Inner();
  11.             in.show();
  12.        }
  13. }

  14. class InnerClassDemo{
  15.        public static void main(String[] args){
  16.              new Outer().method(4);
  17.        }
  18. }

    运行结果:


     匿名内部类

    定义:
    就是内部类的简化写法。

    前提:
    内部类可以继承或实现一个外部类或者接口。

    格式:
    new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}


    简单理解:
    就是建立一个带内容的外部类或者接口的子类匿名对象。


    什么时候使用匿名内部类呢?
    通常使用方法是接口类型参数,并且该接口中的方法不超过三个,可以将匿名内部类作为参数传递。

    好处:
    增强阅读性。

    示例1:
  1. abstract class Demo{
  2.        abstract void show();
  3. }

  4. class Outer{
  5.        int num = 4;

  6.        void method(){
  7.              new Demo(){//匿名内部类
  8.                    void show(){
  9.                         System.out.println("show......" + num);
  10.                   }
  11.              }.show();
  12.        }
  13. }

  14. class InnerClassDemo{
  15.        public static void main(String[] args){
  16.              new Outer().method();
  17.        }
  18. }

    运行结果:


    示例2:  
  1. interface Inter{
  2.        void show1();
  3.        void show2();
  4. }

  5. class Outer{
  6.        public void method(){
  7.             Inter in = new Inter(){
  8.                    public void show1(){
  9.                           System.out.println("...show1...." );
  10.                    }
  11.                    public void show2(){
  12.                           System.out.println("...show2...." );
  13.                    }
  14.             };
  15.             in.show1();
  16.             in.show2();
  17.        }
  18. }

  19. class InnerClassDemo{
  20.        public static void main(String[] args){
  21.              new Outer().method();
  22.        }
  23. }

    运行结果:


    示例3:  
  1. interface Inter{
  2.        void show1();
  3.        void show2();
  4. }

  5. /*
  6. 通常的使用场景之一:
  7. 当函数参数是接口类型时,而且接口中的方法不超过三个。
  8. 可以用匿名内部类作为实际参数进行传递。
  9. */
  10. class InnerClassDemo{
  11.       public static void main(String[] args){
  12.              show(new Inter(){
  13.                    public void show1(){
  14.                         System.out.println("...show1..." );
  15.                    }
  16.                    public void show2(){
  17.                         System.out.println("...show2..." );
  18.                    }
  19.             });
  20.        }
  21.        public static void show(Inter in){
  22.             in.show1();
  23.             in.show2();
  24.        }
  25. }

    运行结果:


    对象的初始化过程

    示例: 
  1. class Fu{
  2.        int num = 9;

  3.        {
  4.             System.out.println("Fu" );
  5.        }

  6.       Fu(){
  7.              super();//Object
  8.              //显示初始化
  9.              //构造代码块初始化
  10.             show();
  11.        }
  12.        void show(){
  13.             System.out.println("fu show " + num);//被覆盖,运行子类的
  14.        }
  15. }

  16. class Zi extends Fu{
  17.        int num = 8;

  18.       {
  19.             System.out.println("Zi" );
  20.       }

  21.       Zi(){
  22.              super();
  23.              //显示初始化
  24.              //构造代码块初始化
  25.             show();
  26.       }

  27.        void show(){
  28.             System.out.println("zi show " + num); 
  29.        }
  30. }

  31. public class Demo{
  32.        public static void main(String[] args){
  33.              new Zi();
  34.        }
  35. }

  运行结果:

 

0 0
原创粉丝点击