zoukankan      html  css  js  c++  java
  • Java多态小知识

     1.

    代码当中体现多态性,其实就是一句话:父类引用指向子类对象。

    格式:
    父类名称 对象名 = new 子类名称();
    或者:
    接口名称 对象名 = new 实现类名称();

    public class Multi {
    
        public static void main(String[] args) {
            // 使用多态的写法
            // 左侧父类的引用,指向了右侧子类的对象
            Fu obj = new Zi();
    
            obj.method();
            obj.methodFu();
        }
    }
    
    public class Fu {
    
        public void method() {
            System.out.println("父类方法");
        }
    
        public void methodFu() {
            System.out.println("父类特有方法");
        }
    
    }
    
    public class Zi extends Fu {
    
        @Override
        public void method() {
            System.out.println("子类方法");
        }
    }

    2.

    在多态的代码当中,成员方法的访问规则是:
        看new的是谁,就优先用谁,没有则向上找。

    口诀:编译看左边,运行看右边。

    对比一下:
    成员变量:编译看左边,运行还看左边。
    成员方法:编译看左边,运行看右边。

    public class MultiMethod {
    
        public static void main(String[] args) {
            Fu obj = new Zi(); // 多态
    
            obj.method(); // 父子都有,优先用子
            obj.methodFu(); // 子类没有,父类有,向上找到父类
    
            // 编译看左边,左边是Fu,Fu当中没有methodZi方法,所以编译报错。
    //        obj.methodZi(); // 错误写法!
        }
    
    }
    
    
    
    public class Fu /*extends Object*/ {
    
        int num = 10;
    
        public void showNum() {
            System.out.println(num);
        }
    
        public void method() {
            System.out.println("父类方法");
        }
    
        public void methodFu() {
            System.out.println("父类特有方法");
        }
    
    }
    
    
    public class Zi extends Fu {
    
        int num = 20;
    
        int age = 16;
    
        @Override
        public void showNum() {
            System.out.println(num);
        }
    
        @Override
        public void method() {
            System.out.println("子类方法");
        }
    
        public void methodZi() {
            System.out.println("子类特有方法");
        }
    }
    
    

    3.

    访问成员变量的两种方式:

    1. 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
    2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找。

    public class MultiField {
    
        public static void main(String[] args) {
            // 使用多态的写法,父类引用指向子类对象
            Fu obj = new Zi();
            System.out.println(obj.num); // 父:10
    //        System.out.println(obj.age); // 错误写法!
            System.out.println("=============");
    
            // 子类没有覆盖重写,就是父:10
            // 子类如果覆盖重写,就是子:20
            obj.showNum();
        }
    
    }

    4.

    向上转型一定是安全的,没有问题的,正确的。但是也有一个弊端:
    对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。

    解决方案:用对象的向下转型【还原】。

    public class Demo {
    
        public static void main(String[] args) {
            // 对象的向上转型,就是:父类引用指向之类对象。
            Animal animal = new Cat(); // 本来创建的时候是一只猫
            animal.eat(); // 猫吃鱼
    
    //        animal.catchMouse(); // 错误写法!
    
            // 向下转型,进行“还原”动作
            Cat cat = (Cat) animal;
            cat.catchMouse(); // 猫抓老鼠
    
            // 下面是错误的向下转型
            // 本来new的时候是一只猫,现在非要当做狗
            // 错误写法!编译不会报错,但是运行会出现异常:
            // java.lang.ClassCastException,类转换异常
            Dog dog = (Dog) animal;
        }
    
    }
    
    
    public class Dog extends Animal {
        @Override
        public void eat() {
            System.out.println("狗吃SHIT");
        }
    
        public void watchHouse() {
            System.out.println("狗看家");
        }
    }
    
    public class Cat extends Animal {
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    
        // 子类特有方法
        public void catchMouse() {
            System.out.println("猫抓老鼠");
        }
    }
    
    public abstract class Animal {
    
        public abstract void eat();
    
    }
    
    
    

    5.
    如何才能知道一个父类引用的对象,本来是什么子类?
    格式:
    对象 instanceof 类名称
    这将会得到一个boolean值结果,也就是判断前面的对象能不能当做后面类型的实例。

    
    public class Demo02Instanceof {
    
        public static void main(String[] args) {
            Animal animal = new Dog(); // 本来是一只狗
            animal.eat(); // 狗吃SHIT
    
            // 如果希望掉用子类特有方法,需要向下转型
            // 判断一下父类引用animal本来是不是Dog
            if (animal instanceof Dog) {
                Dog dog = (Dog) animal;
                dog.watchHouse();
            }
            // 判断一下animal本来是不是Cat
            if (animal instanceof Cat) {
                Cat cat = (Cat) animal;
                cat.catchMouse();
            }
    
            giveMeAPet(new Dog());
        }
    
        public static void giveMeAPet(Animal animal) {
            if (animal instanceof Dog) {
                Dog dog = (Dog) animal;
                dog.watchHouse();
            }
            if (animal instanceof Cat) {
                Cat cat = (Cat) animal;
                cat.catchMouse();
            }
        }
    
    }

    ---------------------------------------------多态案例(USB接口)-------------------------------------

    public interface USB {
    
        public abstract void open(); // 打开设备
    
        public abstract void close(); // 关闭设备
    
    }
    
    public class Computer {
    
        public void powerOn() {
            System.out.println("笔记本电脑开机");
        }
    
        public void powerOff() {
            System.out.println("笔记本电脑关机");
        }
    
        // 使用USB设备的方法,使用接口作为方法的参数
        public void useDevice(USB usb) {
            usb.open(); // 打开设备
            if (usb instanceof Mouse) { // 一定要先判断
                Mouse mouse = (Mouse) usb; // 向下转型
                mouse.click();
            } else if (usb instanceof Keyboard) { // 先判断
                Keyboard keyboard = (Keyboard) usb; // 向下转型
                keyboard.type();
            }
            usb.close(); // 关闭设备
        }
    
    }
    
    // 键盘就是一个USB设备
    public class Keyboard implements USB {
        @Override
        public void open() {
            System.out.println("打开键盘");
        }
    
        @Override
        public void close() {
            System.out.println("关闭键盘");
        }
    
        public void type() {
            System.out.println("键盘输入");
        }
    }
    
    
    // 鼠标就是一个USB设备
    public class Mouse implements USB {
        @Override
        public void open() {
            System.out.println("打开鼠标");
        }
    
        @Override
        public void close() {
            System.out.println("关闭鼠标");
        }
    
        public void click() {
            System.out.println("鼠标点击");
        }
    }
    
    public class DemoMain {
    
        public static void main(String[] args) {
            // 首先创建一个笔记本电脑
            Computer computer = new Computer();
            computer.powerOn();
    
            // 准备一个鼠标,供电脑使用
    //        Mouse mouse = new Mouse();
            // 首先进行向上转型
            USB usbMouse = new Mouse(); // 多态写法
            // 参数是USB类型,我正好传递进去的就是USB鼠标
            computer.useDevice(usbMouse);
    
            // 创建一个USB键盘
            Keyboard keyboard = new Keyboard(); // 没有使用多态写法
            // 方法参数是USB类型,传递进去的是实现类对象
            computer.useDevice(keyboard); // 正确写法!也发生了向上转型
            // 使用子类对象,匿名对象,也可以
    //        computer.useDevice(new Keyboard()); // 也是正确写法
    
            computer.powerOff();
            System.out.println("==================");
    
            method(10.0); // 正确写法,double --> double
            method(20); // 正确写法,int --> double
            int a = 30;
            method(a); // 正确写法,int --> double
        }
    
        public static void method(double num) {
            System.out.println(num);
        }
    
    }
    
    
  • 相关阅读:
    [OpenJudge90][序列DP+乱搞]滑雪
    [OpenJudge8786][暴力DP]方格取数
    [OpenJudge8782][划分DP]乘积最大
    [OpenJudge8471][划分DP]切割回文
    [OpenJudge8462][序列DP]大盗阿福
    【棋盘DP】【OpenJudge7614】最低通行费
    【OpenJudge8464】【序列DP】股票买卖
    bzoj1674: [Usaco2005]Part Acquisition 裸dijkstra
    bzoj3040 最短路+配对堆优化
    poj1330|bzoj3732|noip2013 货车运输 kruskal+倍增lca
  • 原文地址:https://www.cnblogs.com/chenxiaoge/p/13335482.html
Copyright © 2011-2022 走看看