Java多态-抽象-静态-最终

一、多态【重点】【掌握】

1.1 概述

  • 生活中的多态

    • 事物在人脑中的主观印象

    • 狗--》动物

  • 程序中的多态

    • 声明的变量类型是父类类型

    • 创建的对象类型是子类类型

    • 父类变量存储的是子类对象的地址

    • 父类引用指向子类对象

1.2 多态的特点

  • 多态方式创建对象只能使用声明的类型中的属性和方法

    • 方法存在重写

    • 属性不存在覆盖【访问的属性依旧是父类中的内容】

  • 如果方法被子类重写,执行的是重写之后的方法

1.3 动态使用--父类声明为方法形参【重点】【掌握】

  • 能接收父类和子类类型的对象

Human
package com.shine.polymorphic01;
​
public class Human {
    public void dance() {
        System.out.println("人跳舞是为了祭天酬神");
    }
}
Man
package com.shine.polymorphic01;
​
public class Man extends Human {
    @Override
    public void dance() {
        System.out.println("男人喜欢tiao迪斯科");
    }
}
Woman
package com.shine.polymorphic01;
​
public class Woman extends Human {
    @Override
    public void dance() {
        System.out.println("女人喜欢跳广场舞");
    }
}
Demo01
package com.shine.polymorphic01;
​
public class Demo01 {
    public static void main(String[] args) {
        /**
         *  展示人跳舞的信息
         */
        // 正常创建对象
        Human human = new Human();
        dance(human);
        
        Man man = new Man();
        dance(man);
        
        Woman woman = new Woman();
        dance(woman);
    }
    
    /**
     *  展示跳舞的方法
     * @param human
     */
    public static void dance(Human human) { 
        human.dance();
    }
    
}

1.4 多态使用-声明为方法返回值类型【重点】【掌握】

  • 能返回父类和子类类型的对象

Auto
package com.shine.polymorphic02;
​
/**
 *  所有车子的父类
 */
public class Auto {
    public void run() {
        System.out.println("车子能行驶");
    }
}
Bus
package com.shine.polymorphic02;
​
public class Bus extends Auto {
    @Override
    public void run() {
        System.out.println("公交车载人");
    }
}
Car
package com.shine.polymorphic02;
​
public class Car extends Auto {
​
}
Demo01
package com.shine.polymorphic02;
​
import java.util.Scanner;
​
public class Demo01 {
    public static void main(String[] args) {
        /**
         *  编写方法买车,输出车子的编号,返回对应类型的车
         */
        System.out.println("欢迎来到红浪漫汽车店,请选择您需要的车子【1==小轿车,2==公交车,3==拖拉机,4==摩托车】:");
​
        // 提示输入并获取车子型号
        Scanner sc = new Scanner(System.in);
        int autoNo = sc.nextInt();
        
        // 调用方法获取对象
        Auto auto = buyAuto(autoNo);
        
        System.out.println(auto.getClass());
    }
    
    /**
     *  买车的方法
     * @param autoNo    车子的编号
     * @return          车子对象
     */
    public static Auto buyAuto(int autoNo) {
        Auto auto = null;
        switch (autoNo) {
            case 1:
                auto = new Car();
                break;
            case 2:
                auto = new Bus();
                break;
            case 3:
                auto = new Tractor();
                break;
            case 4:
                auto = new MotoBike();
                break;
    
            default:
                auto = new Auto();
                break;
        }
        
        return auto;
    }
}

1.5 类型转换

向上转型
  • 声明的类型是父类,实际引用指向【保存对象的地址】的对象是子类

  • 天生安全,多态的核心使用方式

向下转型
  • 声明的类型是子类,引用执行父类

  • 有风险,可能造成类型转换异常

Animal
package com.shine.polymorphic03;
​
public class Animal {
    public void eat() {
        System.out.println("动物需要进食...");
    }
}
Cat
package com.shine.polymorphic03;
​
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫咪喜欢吃鱼");
    }
}
Dog
package com.shine.polymorphic03;
​
public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗子喜欢吃肉");
    }
}
Demo01
package com.shine.polymorphic03;
​
public class Demo01 {
    public static void main(String[] args) {
        /**
         *  父类
         *      Animal
         *  子类
         *      Dog
         *      Cat
         */
        
        // 正常创建对象:声明的类型和实际创建的类型是相同的
        Animal a = new Animal();
        
        // 动态方式创建对象:声明的类型是父类,实际创建对象是子类类型
        // 向上转型
        Animal aa = new Dog();
        
        // 向下转型
        Dog dog = (Dog) aa;
        System.out.println(dog.getClass());
        
        // 向下转型,声明类型和对象类型不匹配,报错:java.lang.ClassCastException
        //Cat cat = (Cat) aa;
        //System.out.println(cat.getClass());
        // 判定对象是否属于指定类型
        System.out.println(aa instanceof Animal);
        System.out.println(aa instanceof Dog);
        System.out.println(aa instanceof Cat);
    }
}

1.6 练习题

父类声明为方法形参
  • Worker父类

    • Cook

    • Driver

    • Programmer

  • 编写方法,展示这个工人工作的方式

父类声明为方法返回值类型
  • 编写方法点餐,返回下面类型的对象之一

  • Food父类

    • 东坡肉

    • 西湖醋鱼

    • 扬州炒饭

    • 鸭血粉丝汤

  • 展示食物的信息

二、抽象

2.1 概述

  • 使用abstract修饰的内容成为抽象

    • 抽象类

    • 抽象方法

2.2 抽象类

 *  在Java中有些累不适合直接创建对象
 *      创建的对象不能准确表示现实中的任何对象
 *      应该限制其创建对象
 *  使用abstract修饰类,这样的类成为抽象类,不能直接创建对象
抽象类Human
package com.shine.abstract01;
​
/**
 *  抽象类Human
 *      创建的对象不够具体,限制创建对象
 */
public abstract class Human {
    String name;
    int age;
    String gender;
    
    public void eat() {}
    
    public void sleep() {}
}
抽象类的作用
  • 当前其他类的父类

    • 提供多个子类中共有的属性和方法

  • 在创建对象时候声明为父类类型

    • 更自然的使用多态

package com.shine.abstract01;
​
public class Woman extends Human {
​
}
package com.shine.abstract01;
​
public class Demo01 {
    public static void main(String[] args) {
        /**
         *  在Java中有些累不适合直接创建对象
         *      创建的对象不能准确表示现实中的任何对象
         *      应该限制其创建对象
         *  使用abstract修饰类,这样的类成为抽象类,不能直接创建对象
         */
        
        // 声明的类型父类,创建的对象类型是子类
        Human h01 = new Man();
        Human h02 = new Woman();
    }
}

2.3 抽象方法

  • 有些方法在父类中定义,方法的实现部分多余

    • 动物类类中吃饭的方法:动物都会吃饭,吃饭的方式多数不同,子类一般需要重写这些方法

    • 可以把方法的声明部分保留,实现部分删除,定义成为抽象方法

  • 如果父类中存在抽象方法

    • 子类重写所有抽象方法

    • 或者子类也是抽象类

Auto抽象类
package com.shine.abstract02;
​
public abstract class Auto {
    public abstract void start();
    
    public void stop() {
        System.out.println("车子需要能停止");
    }
}
Car
package com.shine.abstract02;
​
public class Car extends Auto {
​
    @Override
    public void start() {
        System.out.println("小轿车使用电启动");
    }
​
}
Tractor
package com.shine.abstract02;
​
public class Tractor extends Auto {
​
    @Override
    public void start() {
        System.out.println("拖拉机使用摇把启动");
    }
}
Demo01
package com.shine.abstract02;
​
public class Demo01 {
    public static void main(String[] args) {
        Auto auto01 = new Car();
        auto01.start();
        auto01.stop();
    }
}

三、static

3.1 概述

  • 被static修饰的内容成为静态的内容

    • static修饰的变量成为静态属性,也称为类属性

    • static修饰的方法成为静态方法,也称为类方法

    • 静态的数据随着类的加载而加载,无需等待对象创建即可使用【使用类名直接调用】

3.2 静态变量【掌握】

  • 使用static修饰的变量成为静态变量

  • 此类创建的所有对象共用一个静态变量

  • 如果在任何位置修改了静态变量,其他所有对象都会收到影响

Korean
package com.shine.static01;
​
public class Korean {
    String name;
    int age;
    // 类变量
    static String capital = "汉城";
    
    public void show() {
        System.out.println("Korean [name=" + name + ", age=" + age + ", capital=" + capital + "]");
    }
}
Demo01
package com.shine.static01;
​
public class Demo01 {
    public static void main(String[] args) {
        // 静态属性 == 类属性,跟随类一起加载进入内存,无序创建对象即可使用
        System.out.println(Korean.capital);
        
        // 创建对象
        Korean k01 = new Korean();
        k01.name = "李二顺";
        k01.age = 18;
        k01.show();
        
        Korean k02 = new Korean();
        k02.name = "金三顺";
        k02.age = 23;
        k02.show();
        
        k01.age = 19;
        k01.show();
        k02.show();
        
        System.out.println("--------------------------");
        
        // k02.capital = "首尔";
        // 静态的数据存储在方法区,和类对象放在一起,是类变量,推荐使用类名直接调用
        Korean.capital = "首尔";
        k01.show();
        k02.show();
    }
}

3.3 课堂案例

  • 统计一个类在运行期间创建了多少对象

package com.shine.static01;
​
public class User {
    String name;
    // 静态的属性,用来记录创建对象的次数
    private static int count = 0;
    
    public User() {
        count++;
    }
    
    public User(String name) {
        this.name = name;
        count++;
    }
    
    public static int getCount() {
        return count;
    }
    
}
package com.shine.static01;
​
public class Demo02 {
    public static void main(String[] args) {
        /**
         *  User
         *      统计一个类在运行期间创建了多少对象
         */
        
        for (int i = 0; i < 150; i++) {
            new User();
        }
        System.out.println(User.getCount());
    }
}

3.4 静态方法【掌握】

  • 使用static修饰的方法成为静态方法【类方法】

  • 可以使用类名直接调用【不用创建对象即可调用】

  • 静态方法中只能访问静态数据,不能访问非静态数据、不能访问this、super

package com.shine.static01;
​
public class User {
    String name = "张三";
    // 静态的属性,用来记录创建对象的次数
    private static int count = 0;
    
    public User() {
        count++;
    }
    
    public User(String name) {
        this.name = name;
        count++;
    }
    
    public static int getCount() {
        return count;
    }
    
    // 实例方法
    public void show() {
        // 实例方法访问实例属性和静态属性
        System.out.println(name);
        System.out.println(count);
        
        // 实例方法调用实例方法和静态方法
        showStatic();
        System.out.println(this);
    }
    
    // 静态方法
    public static void showStatic() {
        // 实例属性需要先创建对象才能使用,静态方法中不能访问实例遍历【静态早于实例】
        // System.out.println(name);
        System.out.println(count);
        
        // 静态的方法不能调用非静态的方法
        // show();
        // System.out.println(this);
        // System.out.println(super);
    }
    
}

四、代码块

4.1 概述

  • 代码块就是使用{}包裹的一块代码

  • 没有名字,自动执行

  • 根据位置和修饰符可以分为:

    • 局部代码块

    • 动态代码块【构造代码块、成员代码块】

    • 静态代码块

    • 同步代码块【多线程部分讲解】

4.2 局部代码块

  • 定义在方法中的代码块称为局部代码块

  • 自动执行,无需【无法】手动调用

package com.shine.block;
​
public class Demo01 {
    public static void main(String[] args) {
        // 局部变量
        int num = 100;
        System.out.println("Hello001");
        System.out.println("Hello002");
        {
            System.out.println("我是局部代码块");
            System.out.println(num);
            
            int ii = 200;
            System.out.println(ii);
        }
        System.out.println("Hello003");
        System.out.println("Hello004");
        // System.out.println(ii);
    }   
}

4.3 动态代码块

  • 动态代码块也称为构造代码块

  • 位置和构造器同一级:类中方法外

  • 构造代码块每一次创建对象都自动执行一次,执行时间早于构造器

  • 可以把构造方法中共同的内容抽取出来放在构造代码块中执行

4.4 静态代码块【掌握】

  • 使用static修饰的代码块成为静态代码块

  • 位置和构造器同一级:类中方法外

  • 静态代码块在程序运行过程中最多执行一次

  • 适用于类的初始化,一般加载驱动使用

package com.shine.block;
​
public class User {
    String name;
    static int count = 0;
    
    static {
        System.out.println("静态代码块");
    }
    
    {
        System.out.println("构造代码块");
        count++;
    }
​
    public User() {
        System.out.println("无参数构造器");
    }
​
    public User(String name) {
        this.name = name;
        System.out.println("有参数构造器");
    }
    
    public static int getCount() {
        return count;
    }
}

4.5 同步代码块

  • 多线程线程安全问题时候讲解

  • 26
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值