Java面向对象进阶(三)

多态

多态的概述,多态的形式

  1. 什么是多态?
    同类型的对象,执行同一个行为,会表现出不同的行为特征
  2. 多态的常见形式
    在这里插入图片描述
  3. 多态中成员访问特点
    ○ 方法调用:编译看左边,运行看右边
class Animal{
    public void run(){
        System.out.println("动物跑~");
    }
}
class Dog extends Animal{
    public void run() {
        System.out.println("狗跑~");
    }
}
class Tortoise extends Animal {
    public void run() {
        System.out.println("乌龟跑~");
    }
}
public class Test1 {
    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.run();  // 狗跑~
        Animal animal1 = new Tortoise();
        animal1.run();  // 乌龟跑~
    }
}

○ 变量调用:编译看左边,运行也看左边(多态侧重行为多态

class SportMan {
    public String name = "运动员";
}
class Swimmer extends SportMan{
    public String name = "游泳运动员";
}
class BasketballPlayer extends SportMan{
    public String name = "篮球运动员";
}
public class Test2 {
    public static void main(String[] args) {
        SportMan sportMan = new Swimmer();
        System.out.println(sportMan.name);  // 运动员
        
        SportMan sportMan1 = new BasketballPlayer();
        System.out.println(sportMan1.name);  // 运动员
    }
}
  • 多态的前提
    ○ 有继承/实现类;有父类引用指向子类对象;有方法重写

多态的优缺点

  • 优势:
    ○ 在多态形式下,右边对象可以实现解耦合,便于扩展和维护
    ○ 定义方法的时候,使用父类作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性欲便利性

  • 劣势
    ○ 多态下不能使用子类的独有功能

class Animal{
    public void run() {
        System.out.println("动物跑~");
    }
}
class Dog extends Animal{
    public void bark() {
        System.out.println("狗在吠~");
    }
}
class Cat extends Animal{
    public void sheep() {
        System.out.println("猫在睡~");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog();
        // animal.bark(); // 报错
        Animal animal1 = new Cat();
        // animal1.sheep(); // 报错
    }
}

多态下引用数据类型的类型转换

  1. 自动类型转换(从子到父): 子类对象赋值给父类类型的变量指向
  2. 强制类型转换(从父到子)
  • 此时必须进行强制类型转换;子类 对象变量 = (子类)父类类型的变量
  • 作用;可以解决多态下的劣势,可以实现调用子类独有的功能
  • 注意:如果转型后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现ClassCastException
class Animal{
    public void run() {
        System.out.println("动物跑~");
    }
}
class Dog extends Animal{
    public void bark() {
        System.out.println("狗在吠~");
    }
}
class Cat extends Animal{
    public void sheep() {
        System.out.println("猫在睡~");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog();
        Dog dog = (Dog) animal;  // 强制转换
        dog.bark();  // 狗在吠~
        ((Dog) animal).bark(); // 狗在吠~

        // Cat cat = (Cat) animal; // 报错
        // cat.sheep();
    }
}

3.Java建议强转换前使用instanceof判断当前对象的真实类型,再进行强制转换

  • 格式:变量名 instanceof 真实类型
  • 用法:判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其他子类类型,是则返回true,反之。
class Animal {
    public void run() {
        System.out.println("动物跑~");
    }
}
class Dog extends Animal{
    public void run() {
        System.out.println("狗跑~");
    }
}
class Cat extends Animal{
    public void run() {
        System.out.println("猫跑~");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Cat();
        if (animal instanceof Cat) {
            System.out.println("猫类对象");  // 执行
        } else if (animal instanceof Dog) {
            System.out.println("狗类对象");
        }
    }
}

多态综合案例

  • 需求:
  1. 使用面向对象编程模拟:设计一个电脑对象,可以安装2个USB设备
  2. 鼠标:被安装时可以完成接入、调用点击功能、拔出功能
  3. 键盘:被安装时可以完成接入、调用打字功能、拔出功能
 interface USB {
    void connect();
    void unconnect();
}
class Mouse implements USB{
    private String name;

    public Mouse(String name) {
        this.name = name;
    }

    @Override
    public void connect() {
        System.out.println(name + "已成功接入");
    }

    @Override
    public void unconnect() {
        System.out.println(name + "已成功弹出");
    }
    public void click() {
        System.out.println(name + "被点击了");
    }
}
class keyBoard implements USB {
    private String name;

    public keyBoard(String name) {
        this.name = name;
    }

    @Override
    public void connect() {
        System.out.println(name + "已成功接入");
    }

    @Override
    public void unconnect() {
        System.out.println(name + "已成功弹出");
    }
    public void input() {
        System.out.println(name + "成功输入");
    }
}
class Computer {
    public void install(USB usb) {
        usb.connect();
        if (usb instanceof Mouse) {
            ((Mouse) usb).click();
        } else if (usb instanceof keyBoard) {
            ((keyBoard) usb).input();
        }
        usb.unconnect();
    }
}
public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();
        USB usb = new Mouse("惠普鼠标");
        computer.install(usb);
        System.out.println("--------------------");
        USB usb1 = new keyBoard("惠普键盘");
        computer.install(usb1);
    }

}

内部类

内部类概述

  1. 内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)
    -在这里插入图片描述
  2. 内部类的使用场景、作用
  • 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计
  • 内部类通常可以方便访问外部类的成员,包括私有的成员
  • 内部类提供更好的封装性,内部类本身就可以用private protected等修饰,封装性可以做更多控制

内部类之一:静态内部类[了解]

  1. 什么是静态内部类?
  • 有static修饰,属于外部类本身
  • 它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已
    在这里插入图片描述
  1. 静态内部类创建对象的格式:
    在这里插入图片描述
class Outer {
    public static class Inner {
        private int onlineNumber = 30;
        private String name = "张三";
        public void show() {
            System.out.println("静态成员内部类");
        }

        public Inner() {
        }

        public Inner(int onlineNumber, String name) {
            this.onlineNumber = onlineNumber;
            this.name = name;
        }

        public int getOnlineNumber() {
            return onlineNumber;
        }

        public void setOnlineNumber(int onlineNumber) {
            this.onlineNumber = onlineNumber;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        System.out.println(inner.getName());  // 张三
        System.out.println(inner.getOnlineNumber());  // 30
        inner.show();  // 静态成员内部类
    }
}
  1. 静态内部类的访问拓展:
  • 静态内部类中可以直接访问外部类的静态成员,外部类的静态成员只有一份可以被共享访问
  • 静态内部类中不可以直接访问外部类的实例成员,外部类的实例成员必须用外部类对象访问

内部类之二:成员内部类[了解]

  1. 什么是成员内部类?
  • 无static修饰,属于外部类的对象
  • JDK16之前,成员内部类中不能定义静态成员变量,JDK16开始可以定义静态成员
    在这里插入图片描述
  1. 成员内部类创建对象的格式:
    在这里插入图片描述
public class Outer {
    public String name = "张三";
    public  String schoolName = "蓝翔技术专修学院";
    public class Inner {
        public static int num = 0;
        public void show() {
            System.out.println("姓名:" + name + "\t" + "学校:" + schoolName);  // 直接访问外部类
        }
    }
}
class Test {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer().new Inner();
        inner.show();  // 姓名:张三	学校:蓝翔技术专修学院
    }
}
  1. 成员内部类的访问拓展:
  • 成员内部类中可以直接访问外部类的静态成员,外部类的静态成员只有一份可以被共享访问
  • 成员内部类的实例方法中可以直接访问外部类的实例成员,因为必须先有外部类对象,才能有成员内部类对象,所有可以直接访问外部类对象的实例成员
  1. 成员内部类-面试题
  • 请观察如下代码,写出合适的代码对应其注释要求输出结果
    在这里插入图片描述
public class People {
    private int heartbeat = 150;
    public class Heart {
        private int heartbeat = 110;
        public void show() {
            int heartbeat = 70;
            System.out.println(heartbeat); // 78
            System.out.println(this.heartbeat); // 110
            System.out.println(People.this.heartbeat); // 150
        }
    }
}
class Test1 {
    public static void main(String[] args) {
        People.Heart heart = new People().new Heart();
        heart.show();
    }
}
  • 注意:在成员内部类中访问所在外部类对象,格式:外部类名.this

内部类之三:局部内部类[了解]

  • 局部内部类放在方法、代码块、构造器等执行体中
  • 局部内部类的类文件名为:外部类$N内部类.class

内部类之四:匿名内部类概述[重点]

  1. 匿名内部类:
  • 本质上是一个没有名字的1局部内部类,定义在方法中、代码块中、等
  • 作用:方便创建子类对象,最终目的为了简化代码编写
  1. 格式:
    在这里插入图片描述
    在这里插入图片描述
  2. 特点总结:
  • 匿名内部类是一个没有名字的内部类
  • 匿名内部类写出来就会产生一个匿名内部类的对象
  • 匿名内部类的对象类型相当于是当前new的那个的类型的子类类型
public abstract class Animal {
    public abstract void run();
}
//class Tiger extends Animal {
//
//    @Override
//    public void run() {
//        System.out.println("老虎跑得很快~");
//    }
//}
class Test {
    public static void main(String[] args) {
//        Animal animal = new Tiger();
//        animal.run();  // 老虎跑得很快~
        Animal animal = new Animal() {
            @Override
            public void run() {
                System.out.println("老虎跑得很快~");
            }
        };
        animal.run(); // 老虎跑得很快~
    }
}

匿名内部类常见使用形式

public class Test2 {
    public static void main(String[] args) {
        go(new Swimming() {
            @Override
            public void swim() {
                System.out.println("运动员跑得很快~");
            }
        });
    }
    public static void go(Swimming swimming) {
        System.out.println("开始~");
        swimming.swim();
        System.out.println("结束~");
    }
}
interface Swimming {
    void swim();
}

使用总结:匿名内部类可以作为方法的实际参数进行传输

匿名内部类真实使用场景演示

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Test3 {
    public static void main(String[] args) {
        // 1.创建窗口
        JFrame win = new JFrame("登录界面");
        JPanel panel = new JPanel();
        win.add(panel);

        // 2.创建一个按钮对象
        JButton btn = new JButton("登录");

        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(win,"点我一下,说明爱我!");
            }
        });

        //  3.把按钮对象添加到桌布上显示
        panel.add(btn);

        // 4.展示窗口
        win.setSize(400,300);
        win.setLocationRelativeTo(null);
        win.setVisible(true);
    }
}

常用API

  1. 什么是API?
  • API(Application Programming interface)应用程序编程接口
  • 简单来说:就是Java帮我们已经写好的一些方法,我们直接拿过来用就可以了

Object

  1. Object类的作用;
  • 一个类要么默认继承了Object类,要么简介继承了Object类,Object类是Java中的祖宗类
  • Object类的方法是一切子类都可以直接使用的,所有我们要学习Object类的方法

toString方法

  1. Object的toString方法:
方法名说明
public String toString()默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址
  1. 问题引出
  • 开发中直接输出对象,默认输出对象的地址其实是毫无意义的
  • 开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息
  1. toString存在的意义
  • 父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息!!
public class Test {
    public static void main(String[] args) {
        Student student = new Student("张三","男","蓝翔技术专修专业");
        System.out.println(student);
    }
}
class Student {
    private String name;
    private String sex;
    private String major;

    public Student() {
    }

    public Student(String name, String sex, String major) {
        this.name = name;
        this.sex = sex;
        this.major = major;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", major='" + major + '\'' +
                '}';
    }
}

equals方法

  1. Object的equals方法:
方法名说明
public Boolean equals (Object o)默认是比较当前对象与另一个对象的地址是否相同,相同返回true,不同返回false
  1. 问题思考
  • 直接比较两个对象的地址是否相同完全可以用“==”代替equals
  1. equals存在的意义
  • 父类equals方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则

○ 重写子类方法

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name) && Objects.equals(sex, student.sex) && Objects.equals(major, student.major);
    }

○ 使用重写方法

public class Test2 {
    public static void main(String[] args) {
        Student student1 = new Student("张三","男","蓝翔技术专修学院");
        Student student2 = new Student("李四","男","五道口理工学院");
        Student student3 = new Student("张三","男","蓝翔技术专修学院");
        System.out.println(student1.equals(student2));  // false
        System.out.println(student1.equals(student3));  // true
    }
}

Objects

  1. Objects概述
  • Objects类与Object还是继承关系,Object类是从JDK1.7开始之后才有的
  • Objects的equals方法比较的结果是一样的,但是更安全
  1. Objects的常见方法:
方法名说明
public static boolean equals(Object a, Object b)比较两个对象的,底层会进行非空判断,从而可以避免空指针异常。再进行equals比较
public static boolean isNull (Object obj)判断变量是否为null,为null返回true,反之
public class Test {
    public static void main(String[] args) {
        String question = null;
        String answer = "略";

        // System.out.println(question.equals(answer));  // 报错
        System.out.println(Objects.equals(question,answer));  // false
    }
}
import java.util.Objects;

public class Test2 {
    public static void main(String[] args) {
        String name = "张三";
        String sex = null;

        System.out.println(Objects.isNull(name));  // false
        System.out.println(Objects.isNull(sex));  // true
    }
}

StringBuilder

  1. StringBuilder概述
  • StringBuilder是一个可变的字符串类,我们可以把它看成是一个对象容器
  • 作用:提高字符串的操作效率,如拼接、修改等
  1. StringBuilder构造器
名称说明
public StringBuilder()创建一个空白的可变的字符串对象,不包含任何内容
public StringBuilder(String str)创建一个指定字符串内容的可变字符串对象
  1. StringBuilder常用方法
方法名称说明
public StringBuilder append(任意类型)添加数据并返回StringBuilder对象本身
public String reverse()将对象的内容反转
public int length()返回对象内容长度
public String toString()通过toString()就可以实现把StringBuilder转换为String
public class Test {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder();
        // 支持链式编程
        System.out.println(stringBuilder.append(123).append("abc").append("我爱你中国"));
        // 123abc我爱你中国
        System.out.println(stringBuilder.reverse());
        // 国中你爱我cba321
        System.out.println(stringBuilder.length()); // 11
        // way(stringBuilder);  // 报错
        way(stringBuilder.toString());  // ok
        StringBuilder stringBuilder1 = new StringBuilder("我爱你中国");
        System.out.println(stringBuilder1);  // 我爱你中国
    }
    public static void way (String s) {
        System.out.println("ok");
    }
}

Math

  1. Math类
  • 包含执行基本数字运算的方法,Math类没有提供公开的构造器
  • 如何使用类中的成员呢?看类的成员是否都是静态的,如果是,通过类名就可以直接调用
  1. Math类的常用方法
方法名说明
public static int abs(int a)获取参数绝对值
public static double ceil(double a)向上取整
public static double floor(double a)向下取整
public static int round(float a)四舍五入
public static int max(int a,int b)获取两个int值中的较大值
public static double pow(double a,double b)返回a的b次幂的值
public static double random()返回值为double的随机数,范围[0.0,1.0)
public class Test {
    public static void main(String[] args) {
        System.out.println(Math.abs(-2));  // 2
        System.out.println(Math.ceil(3.1));  // 4.0
        System.out.println(Math.floor(4.9));  // 4.0
        System.out.println(Math.round(3.4));  // 3
        System.out.println(Math.max(5,7));  // 7
        System.out.println(Math.pow(2,3));  // 8.0
        System.out.println(Math.random());  // 0.87068800665161
    }
}

System

  1. System类概述
  • System的功能是通用的,都是直接用类名调用即可,所以System不能被实例化
  1. System类的常用方法
方法名说明
public static void exit(int status)终止当前运行的Java虚拟机,非零表示异常终止
public static long curentTimeMillis()返回当前系统的时间毫秒值形式
public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数)数组拷贝
blic class Test {
    public static void main(String[] args) {
//        System.exit(0);

        System.out.println(System.currentTimeMillis());  // 1699282443023

        int[] arr1 = {10,20,30,40,50,60,70};
        int[] arr2 = new int[6];
        System.arraycopy(arr1,3,arr2,2,3);
        System.out.println(Arrays.toString(arr2));  // [0, 0, 40, 50, 60, 0]
    }
}

BigDecimal

  1. BigDecimal作用
  • 用于解决浮点型运算精度失真的问题
  1. 使用步骤
  • 创建对象BigDecimal封装浮点型数据(最好的方式是调用方法)
    在这里插入图片描述
  1. BigDecima常用API
方法名说明
public BigDecimal add(BigDecimal b)加法
public BigDecimal subtract(BigDecimal b)减法
public BigDecimal multiply(BigDecimal b)乘法
public BigDecimal divide(BigDecimal b)除法
public BigDecimal divide(另一个BigDecimal对象,精确几位,舍入模式)除法
import java.math.BigDecimal;
import java.math.RoundingMode;

public class Test {
    public static void main(String[] args) {
        BigDecimal a = BigDecimal.valueOf(2.5);
        BigDecimal b = BigDecimal.valueOf(3.25);
//        1. 加法
        System.out.println(a.add(b));  // 5.75
//        2. 减法
        System.out.println(b.subtract(a));  // 0.75
//        3. 乘法
        System.out.println(a.multiply(b));  // 8.125
//        4. 除法
        // System.out.println(a.divide(b));  // 报错
        // 注意事项,BigDecimal是一定要精确计算的,结果为循环数会报错
        BigDecimal c = BigDecimal.valueOf(5);
        BigDecimal d = BigDecimal.valueOf(2);
        System.out.println(c.divide(d));  // 2.5

        BigDecimal e = BigDecimal.valueOf(10.0);
        BigDecimal f = BigDecimal.valueOf(3.0);
        System.out.println(e.divide(f, 2, RoundingMode.HALF_DOWN));  // 3.33
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值