Java 多态透析 详细理解

1:什么是多态

       一个对象的多种状态

       (老师)(员工)(儿子)

       教师 a =老钟;

       员工 b =老钟;

2:多态体现

  父类引用变量指向了子类的对象          Father f = new Son();

      父类引用也可以接受自己的子类对象

     1:Father类

           1:非静态成员变量x

           2:静态成员变量y

           3:非静态方法eat,方法体输出父类信息

           4:静态方法speak();方法体输出父类信息

class Father {
    int x = 1;
    static int y = 2;
 
    void eat() {
        System.out.println("开吃");
    }
 
    static void speak() {
        System.out.println("小头爸爸");
    }
}

   2:Son类

           1:非静态成员变量x

           2:静态成员变量y

           3:非静态方法eat,方法体输出子类信息

           4:静态方法speak();方法体输出子类信息

class Son extends Father {
    int x = 3;
    static int y = 4;
 
    void eat() {
        System.out.println("大头儿子很能吃");
    }
 
    static void speak() {
        System.out.println("大头儿子。");
    }
}

class Demo1 {
 
    public static void main(String[] args) {
 
        Father f = new Son(); // 父类引用指向了子类对象。
        System.out.println(f.x); // 1
        System.out.println(f.y); // 2
        f.eat(); // 输出的是子类的。
        f.speak(); // 输出的是父类
         
    }
}

  3总结:

  1:当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量

  2:当父类和子类具有相同的静态成员变量,那么在多态下访问的是父类的静态成员变量

             所以:父类和子类有相同的成员变量,多态下访问的是父类的成员变量。

  3:当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类的成员方法

  4:当父类和子类具有相同的静态方法(就是子类重写父类静态方法),多态下访问的是父类的静态方法。  

多态前提

    1:类与类之间有关系,继承或者实现

多态弊端

    1:提高扩展性,但是只能使用父类引用指向父类成员。

多态特点

    非静态

     1:编译时期,参考引用型变量所属的类是否有调用的方法,如果有编译通过。没有编译失败

       2:运行时期,参考对象所属类中是否有调用的方法。

         3:总之成员函数在多态调用时,编译看左边,运行看右边。

          在多态中,成员变量的特点,无论编译和运行  参考左边(引用型变量所属的类)。

          在多态中,静态成员函数特点,无论编译和运行都参考左边

多态练习

    1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。

       1:定义功能,根据输出任何图形的面积和周长。

abstract class MyShape{
    public abstract double getArea();
    public abstract double getLen();
}

     2:定义Rect类继承MyShape

class  Rect extends MyShape{
    double width ;
    double height;
    Rect(){
    }
    Rect(double width ,double height){
        this.width=width;
        this.height=height;
    }
    public double getArea(){
        return width*height;
    }
    public  double getLen(){
        return 2*(width+height);
    }
}

      3:定义Cricle类继承MyShape

class Circle extends MyShape{
     double r;
     public static final double PI=3.14;
     Circle(){
     }
    Circle(double r){
        this.r=r;
     }
    public double getLen(){
        return 2*PI*r;
     }
    public double getArea(){
        return PI*r*r;
     }
}

    4:定义静态方法计算任意图形的面积和周长

           1:未知内容参与运算,不能确定用户传入何种图形,使用多态。

              1:形参定义为 MyShape my

           2:调用计算面积方法,和计算周长方法。并打印

              2:使用多态特性,子类重写了父类非静态方法,会执行子类的方法。

class Demo2{
    public static void main(String[] args){
        System.out.println();
        print(new Rect(3,4)); //MyShape m =new Rect(3,4);
        print(new Circle(3));
        }
        //根据用户传入的图形对象,计算出该图形的面积和周长
        //1:多态可以作为形参,接受范围更广的对象,避免函数重载过度使用。
        public static void print(MyShape m){ 
            System.out.println(m.getLen());
            System.out.println(m.getArea());
        }      
}

 2:多态可以作为返回值类型。

获取任意一辆车对象

           1:定义汽车类,有名字和颜色,提供有参和无参构造,有运行的行为。

class Car {
    String name;
    String color;
    Car() {
    }
    Car(String name, String color) {
        this.name = name;
        this.color = color;
    }
    void run() {
        System.out.println("跑跑。。。。");
    }
}

  2:定义Bmw类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。

class Bmw extends Car {
    Bmw() {
    }
    Bmw(String name, String color) {
        super(name, color);
    }
    void run() {
        System.out.println("宝马很拉风。。。。");
    }
}

   3:定义Benz类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。

class Benz extends Car {
    Benz() {
    }
    Benz(String name, String color) {
        super(name, color);
    }
    void run() {
        System.out.println("奔驰商务首选。。。。");
    }
}

   4:定义Bsj类,继承Car类,提供无参构造和有参构造(super父类构造),重写父类运行行为。

class Bsj extends Car {
    Bsj() {
    }
    Bsj(String name, String color) {
        super(name, color);
    }
    void run() {
        System.out.println("泡妞首选。。。。");
    }
}

           5:定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。

              1:使用(int)Math.round(Math.random()*2); 生成0-2之间随机数。

              2:使用if else 判断,指定,0,1,2 new 不同汽车 并返回。

class Demo3 {
    public static void main(String[] args) {
        int x = 0;
        while (x < 100) {
            Car c = CarFactory();
            c.run();
            x++;
        }
    }
 
    // 定义静态方法,汽车工厂,随机生产汽车。使用多态定义方法返回值类型。
    // 使用随机数,0.1.2 if 0 bsj 1 bmw 2 bc
    public static Car CarFactory() {
        int x = (int) Math.round(Math.random() * 2);
        if (0 == x) {
            return new Bmw("宝马x6", "红色");
        } else if (1 == x) {
            return new Benz("奔驰", "黑色");
        } else if (2 == x) {
            return new Bsj("保时捷", "棕色");
        } else {
            return new Benz("Smart", "红色");
        }
    }
}

3:抽象类和接口都可以作为多态中的父类引用类型。 多态之类型转型

 

1:案例定义Father类

 

       1:定义method1和method2方法

class Father {
    void method1() {
        System.out.println("这是父类1");
    }
    void method2() {
        System.out.println("这是父类2");
    }
}

  2:定义Son类继承Father类

 

       1:定义method1(重写父类method1)和method2方法

class Son extends Father {
    void method1() {
        System.out.println("这是子类1");
    }
    void method3() {
        System.out.println("这是子类3");
    }
}

    3:创建Father f=new Son();

 

       1: f.method1() 调用的子类或者父类?

 

       2: f.method2() 编译和运行是否通过?

 

       3: f.method3() 编译和运行是否通过?(编译报错)

class Demo4 {
    public static void main(String[] args) {
        Father f = new Son();
        f.method1(); // 这是子类1
        f.method2(); // 这是父类2
        // f.method3(); //编译报错。
        // 多态弊端,只能使用父类引用指向父类成员。
        // 类类型转换
        Son s = (Son) f;
        s.method3();
        System.out.println();
    }
}

    4:如何在多态下,使用父类引用调用子类特有方法。

 

       1:基本类型转换:

 

           1:自动:小->大

 

           2:强制:大->小

 

       2:类类型转换

 

           前提:继承,必须有关系

 

           1:自动:子类转父类

 

           2:强转:父类转子类

 

           3:类型转换

 

              1:Son s=(Son)f

 

              2:s.method3();

案例:

      1:定义Animal类颜色成员变量,无参构造,有参构造,run方法

class Animal {
    String color;
    Animal() {
    }
    Animal(String color) {
        this.color = color;
    }
    void run() {
        System.out.println("跑跑");
    }
}

  2:定义Dog类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Dog的特有方法ProtectHome

class Dog extends Animal {
    Dog() {
    }
    Dog(String color) {
        super(color);
    }
    void run() {
        System.out.println("狗儿跑跑");
    }
    void protectHome() {
        System.out.println("旺旺,看家");
    }
}

  3:定义Fish类,继承Animal,定义无参构造,有参构造(使用super调用父类有参构造),Fish特有方法swim

class Fish extends Animal {
    Fish() {
    }
    Fish(String color) {
        super(color);
    }
    void run() {
        System.out.println("鱼儿水中游");
    }
    void swim() {
        System.out.println("鱼儿游泳");
    }
}

 4:使用多态,Animal a=new Dog();

     5:调用Dog的特有方法,ProtectHome

       1:类类型转换,Dog d=(Dog)a;

       2:d.protectHome

class Demo5 {
 
    public static void main(String[] args) {
 
        Animal ani = new Dog();
        // ani.protectHome();
        // 正常转换
        Dog d = (Dog) ani;
        d.protectHome();
 
        // 多态例外
        Animal an = new Animal();
        // ClassCastException
        // Dog d=(Dog)an
 
        // 多态例外
        Animal dog = new Dog();
        // ClassCastException
        // Fish f = (Fish) dog;
 
    }
}

   6:非多态

    1:Animal a=new Animal();

       2:类类型转换

           Dog d=(Dog)a; 

           d.protectHome();

        3:编译通过,运行出现异常

           1:ClassCastException

    7:多态例外

           1:Animal  a=new Dog();

           2:类类型转换

              1:Fish f=(Fish)a;

              2:f.fish();

              3:编译通过,运行异常

                  1:ClassCastException

              4:虽然是多态,但是狗不能转为鱼,他们之间没有关系。

案例2  

    1:定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法

    2:使用多态,方法形参,不能确定用户传入的是那种动物

    3:使用instanceof 关键字,判断具体是何种动物,

    4:类转换,执行该动物的特有方法。

class Animal {
    String color;
    Animal() {
    }
    Animal(String color) {
        this.color = color;
    }
    void run() {
        System.out.println("跑跑");
    }
}

class Dog extends Animal {
    Dog() {
    }
    Dog(String color) {
        super(color);
    }
    void run() {
        System.out.println("狗儿跑跑");
    }
    void protectHome() {
        System.out.println("旺旺,看家");
    }
}

class Fish extends Animal {
    Fish() {
    }
    Fish(String color) {
        super(color);
    }
    void run() {
        System.out.println("鱼儿水中游");
    }
    void swim() {
        System.out.println("鱼儿游泳");
    }
}

class Bird extends Animal {
    Bird() {
    }
    Bird(String color) {
        super(color);
    }
    void run() {
        System.out.println("鸟儿空中飞");
    }
    void fly() {
        System.out.println("我是一只小小鸟。。。。");
    }
}

class Demo6 {
    public static void main(String[] args) {
        System.out.println();
        doSomething(new Dog());
        doSomething(new Bird());
        doSomething(new Fish());
    }
    // 定义一功能,接收用户传入动物,根据用于传入的具体动物,执行该动物特有的方法
    public static void doSomething(Animal a) {
        if (a instanceof Dog) {
            Dog d = (Dog) a;
            d.protectHome();
        } else if (a instanceof Fish) {
            Fish f = (Fish) a;
            f.swim();
        } else if (a instanceof Bird) {
            Bird b = (Bird) a;
            b.fly();
        } else {
            System.out.println("over");
        }
    }
}
时间: 2024-10-26 05:20:34

Java 多态透析 详细理解的相关文章

Java设计模式透析:组合(Composite)

听说你们公司最近新推出了一款电子书阅读应用,市场反应很不错,应用里还有图书商城,用户 可以在其中随意选购自己喜欢的书籍.你们公司也是对此项目高度重视,加大了投入力度,决定给此 应用再增加点功能. 好吧,你也知道你是逃不过此劫了,没过多久你的leader就找到了你. 他告诉你目前的应用对每本书的浏览量和销售量做了统计,但现在想增加对每个书籍分类的浏览量和 销售量以及所有书籍总的浏览量和销售量做统计的功能,希望你可以来完成这项功能. 领导 安排的工作当然是推脱不掉的,你只能硬着头皮上了,不过好在这个

Java设计模式透析:模板方法(Template Method)

今天你还是像往常一样来上班,一如既往地开始了你的编程工作. 项目经理告诉你,今天 想在服务器端增加一个新功能,希望写一个方法,能对Book对象进行处理,将Book对象的所有字段以 XML格式进行包装,这样以后可以方便与客户端进行交互.并且在包装开始前和结束后要打印日志, 这样方便调试和问题定位. 没问题!你觉得这个功能简直是小菜一碟,非常自信地开始写起 代码. Book对象代码如下: public class Book { private String bookName; private int

Java设计模式透析:单例(Singleton)

写软件的时候经常需要用到打印日志功能,可以帮助你调试和定位问题,项目上线后还可以帮助 你分析数据.但是Java原生带有的System.out.println()方法却很少在真正的项目开发中使用,甚至 像findbugs等代码检查工具还会认为使用System.out.println()是一个bug. 为什么作为Java 新手神器的System.out.println(),到了真正项目开发当中会被唾弃呢?其实只要细细分析,你就会 发现它的很多弊端.比如不可控制,所有的日志都会在项目上线后照常打印,从

Java设计模式透析:适配器(Adapter)

今天一大早,你的leader就匆匆忙忙跑过来找到你:"快,快,紧急任务!最近ChinaJoy马上就 要开始了,老板要求提供一种直观的方式,可以查看到我们新上线的游戏中每个服的在线人数." 你看了看日期,不是吧!这哪里是马上要开始了,分明是已经开始了!这怎么可能来得及呢 ? "没关系的."你的leader安慰你道:"功能其实很简单的,接口都已经提供好了,你只 需要调用一下就行了." 好吧,你勉为其难地接受了,对于这种突如其来的新需求,你早已 习惯.

Java设计模式透析:策略(Strategy)

今天你的leader兴致冲冲地找到你,希望你可以帮他一个小忙,他现在急着要去开会.要帮什么 忙呢?你很好奇. 他对你说,当前你们项目的数据库中有一张用户信息表,里面存放了很用 户的数据,现在需要完成一个选择性查询用户信息的功能.他说会传递给你一个包含许多用户名的数 组,你需要根据这些用户名把他们相应的数据都给查出来. 这个功能很简单的嘛,你爽快地 答应了.由于你们项目使用的是MySQL数据库,你很快地写出了如下代码: public class QueryUtil { public void fi

Java封装、继承、多态三大特征的理解_java

首先先简单的说一下其3大特性的定义: 封装:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别.将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成"类",其中数据和函数都是类的成员.封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员.封装的基本要求是: 把所有的属性私有化,对每个属性提供getter和setter方法,如果有一个带参的

多视角透析Struts2

3.3 多视角透析Struts2  Struts2的外部环境并不复杂,因为其核心内容非常明确:探究Struts2运行时所必须的基本要素.我们对Struts2的运行环境和Struts2所依赖的核心技术的讲解,更多是为了让读者了解Struts2能够顺利运行的条件.  在明确了Struts2的外部环境之后,我们讨论的话题就将转向Struts2本身.在本节中,我们将从宏观和微观这两个不同的视角,阐述Struts2的总体架构和内部元素构成,以此揭开Struts2的神秘面纱.  3.3.1透视镜 -- St

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

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

java代码-关于java多态的问题,不是很懂。

问题描述 关于java多态的问题,不是很懂. 在java se中为什么利用父类引用指向子类对象.而不直接new子类呢,这样有什么好处? 解决方案 换句话说,每天到吃饭的点,我们习惯会说,"去吃饭",而不是会说"去吃青椒肉丝盖浇饭".父类相当于一个范围,子类相当于一个具体的. 解决方案二: 昨天看到有关java多态的一篇文章,内容如下文章转自:http://blog.csdn.net/thinkGhoster/archive/2008/04/19/2307001.as