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);
        }
    
    }
    
    
  • 相关阅读:
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    使用Jasmine和karma对传统js进行单元测试
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南
    nginx 基于IP的多虚拟主机配置
    Shiro 框架的MD5加密算法实现原理
    项目实战:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)
    实用技巧:阿里云服务器建立公网物联网服务器(解决阿里云服务器端口,公网连接不上的问题)
  • 原文地址:https://www.cnblogs.com/chenxiaoge/p/13335482.html
Copyright © 2011-2022 走看看