Java-面向对象进阶3

目录

一、面向对象三大特征之三:多态

1.多态的概述、多态的形式

2.多态的优势

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

4.多态的案例

二、内部类

1.内部类的概述

2.内部类之一:静态内部类(了解)

3.内部类之二:成员内部类(了解)

4.局部内部类(鸡肋语法,了解即可)

5.匿名内部类(重点)

6.匿名内部类常见使用形式

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

三、常用API

1.Object

2.Objects

 3.StringBuilder

4.Math

5.System

 6.BigDecimal


一、面向对象三大特征之三:多态

1.多态的概述、多态的形式

什么是多态:同类型的对象,执行同一个行为,会表现出不同的行为特征

多态的常见形式:父类类型 对象名称 = new 子类构造器; 接口 对象名称 = new 实现类构造器

多态中成员的访问特点:1.方法调用:编译看左边,运行看右边;2.变量调用:编译看左边,运行也看左边(多态侧重行为多态)

多态的使用前提:有继承/实现关系;有父类引用指向子类对象;有方法重写

package com.pikaqiu.d1_polymorphic;

public abstract class Animal {
    public String name = "父类动物";
    public abstract void run();
}

package com.pikaqiu.d1_polymorphic;

public class Dog extends Animal{
    public String name = "狗动物" ;

    @Override
    public void run() {
        System.out.println("🐕跑的贼快");
    }
}

package com.pikaqiu.d1_polymorphic;

public class Tortoise extends Animal{
    public String name = "乌龟动物" ;

    @Override
    public void run() {
        System.out.println("🐢根本跑不起来");
    }
}

package com.pikaqiu.d1_polymorphic;

public class Test {
    public static void main(String[] args) {
        //多态形式:父类类型 对象名称 = new 子类构造器
        Animal a = new Dog();
        a.run(); //编译看左边,运行看右边
        System.out.println(a.name); //编译看左边,运行还是看左边

        Animal a1 = new Tortoise();
        a1.run();
        System.out.println(a1.name);
    }
}

2.多态的优势

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

多态下会产生的问题:多态下不能使用子类独有的功能

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

自动类型转换(从子到父):子类对象赋值给父亲类型的变量指向

强制类型转换(从父到子):此时必须进行强制类型转换---子类 对象 = (子类)父亲类型的变量

作用:可以解决多态下的劣势,可以实现调用子类独有的功能

注意:如果转换后的类型和对象真实类型不是同一种类型,那么转换时,编译不会出错,但是运行会出现ClassCastException问题

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

package com.pikaqiu.d2_polymorphic_convert;

public class Animal {
    public void run(){
        System.out.println("动物可以跑");
    }
}

package com.pikaqiu.d2_polymorphic_convert;

public class Dog extends Animal{
    @Override
    public void run(){
        System.out.println("🐕跑的很快");
    }

    public void lookDoor(){
        System.out.println("🐕在看🚪");
    }
}

package com.pikaqiu.d2_polymorphic_convert;

public class Tortoise extends Animal{
    @Override
    public void run(){
        System.out.println("🐢跑的很慢");
    }

    public void layEggs(){
        System.out.println("🐢在下蛋");
    }
}

package com.pikaqiu.d2_polymorphic_convert;

public class Test {
    public static void main(String[] args) {
        //自动类型转换
        Animal a = new Dog();
        a.run();

        //强制类型转换
        Animal a1 = new Tortoise();
        a1.run();
        //a1.layEggs();

        //Dog d = (Dog) a1; //强制类型转换,编译阶段不报错(有继承或者实现关系,编译阶段可以强制转换),运行时可能出错

        if(a1 instanceof Tortoise){
            Tortoise t = (Tortoise) a1;
            t.layEggs();
        }else if(a1 instanceof Dog){
            Dog d = (Dog) a1;
            d.lookDoor();
        }
    }
}

4.多态的案例

需求:使用面向对象编程模拟:设计一个电脑对象,可以安装2个USB设备;鼠标:被安装时可以完成插入、调用点击功能、拔出功能;键盘:被安装时可以完成插入、调用打字功能、拔出功能;

package com.pikaqiu.d3_polymorphic_test;

public interface USB {
    void insert();
    void pullOut();
}

package com.pikaqiu.d3_polymorphic_test;

public class Mouse implements USB{

    @Override
    public void insert() {
        System.out.println("鼠标完成接入");
    }

    @Override
    public void pullOut() {
        System.out.println("鼠标已经拔出");
    }

    public void click(){
        System.out.println("开始点击");
    }
}

package com.pikaqiu.d3_polymorphic_test;

public class KeyBoard implements USB{
    @Override
    public void insert() {
        System.out.println("键盘完成接入");
    }

    @Override
    public void pullOut() {
        System.out.println("键盘已经拔出");
    }

    public void type(){
        System.out.println("开始打字");
    }
}

package com.pikaqiu.d3_polymorphic_test;

public class Computer {
    public void installUSB(USB usb){
        //接入
        usb.insert();

        //独有功能
        if(usb instanceof KeyBoard){
            KeyBoard k = (KeyBoard) usb;
            k.type();
        }else if(usb instanceof Mouse){
            Mouse m = (Mouse) usb;
            m.click();
        }

        //拔出
        usb.pullOut();
    }
}

package com.pikaqiu.d3_polymorphic_test;

public class Test {
    public static void main(String[] args) {
        Computer c = new Computer();

        USB u = new KeyBoard();
        c.installUSB(u);

        USB u1 = new Mouse();
        c.installUSB(u1);
    }
}

二、内部类

1.内部类的概述

内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)

内部类的使用场景,作用:1.当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部的事物提供服务,那么整个内部的完整结构可以选择使用内部类设计;2.内部类通常可以方便访问外部类的成员,包括私有成员;3.内部类提供了更好的封装性,内部类本身就可以用private、protected等修饰,封装性可以做更多的控制

内部类的分类:1.静态内部类(了解);2.成员内部类(非静态内部类)(了解);3.局部内部类(了解);4.匿名内部类(重点)

2.内部类之一:静态内部类(了解)

什么是静态内部类:1.有static修饰;2.它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已

静态内部类创建对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部构造器;

使用场景:一个类中包含了一个完整的成分,如汽车类中的发动机类

静态内部类中是否可以直接访问外部类的静态成员?可以,外部类的静态成员只有一份可以被共享访问

静态内部类中是否可以直接访问外部类的实例成员?不可以,外部类的实例成员必须使用外部类对象访问

3.内部类之二:成员内部类(了解)

什么是成员内部类:1.无static修饰,属于外部类的对象;2.JDK16之前,成员内部类中不能定义静态成员,JDK16开始也可以定义静态成员了

成员内部类创建对象的格式: 外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器();

成员内部类中是否可以直接访问外部类的静态成员?可以,外部类的静态成员只有一份可以被共享访问

成员内部类中是否可以直接访问外部类的实例成员?可以,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员

案例:

package com.pikaqiu.d5_innerclass;

public class Test2 {
    public static void main(String[] args) {
        People.Heart heart = new People().new Heart();
        heart.show();
    }
}

class People{
    private int heartbeat = 150;
    public class Heart{
        private int heartbeat = 110;
        public void show(){
            int heartbeat = 78;
            System.out.println(heartbeat); //78
            System.out.println(this.heartbeat); //110
            System.out.println(People.this.heartbeat); //150
        }
    }
}

4.局部内部类(鸡肋语法,了解即可)

1.局部内部类放在方法、代码块、构造器等执行体中;

2.局部内部类的类文件名为:外部类$N内部类.class

5.匿名内部类(重点)

什么是匿名内部类:本质上是一个没有名字的局部内部类,定义在方法中、代码块中、等

作用:方便创建子类对象,最终目的为了简化代码编写

new 类 || 抽象类名 || 接口名(){重写方法};

特点:1.匿名内部类是一个没有名字的内部类;2.匿名内部类写出来就会产生一个匿名内部类的对象;3.匿名内部类的对象类型相当于是当前new的那个类型的子类类型

package com.pikaqiu.d6_innerclass_anonymous;

import static sun.misc.PostVMInitHook.run;

public class Test {
    public static void main(String[] args) {
        Animal a = new Animal() {
            @Override
            public void run() {
                System.out.println("老虎跑得快~~~");
            }
        };
        a.run();
    }
}

//class Tiger extends Animal{
//
//    @Override
//    public void run() {
//        System.out.println("老虎跑的快~~~");
//    }
//}

abstract class Animal{
    public abstract void run();
}

6.匿名内部类常见使用形式

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

package com.pikaqiu.d6_innerclass_anonymous;

public class Test2 {
    public static void main(String[] args) {
//        Swimming s = new Swimming() {
//            @Override
//            public void swim() {
//                System.out.println("学生快乐的自由泳");
//            }
//        };
        go(new Swimming() {
            @Override
            public void swim() {
                System.out.println("学生快乐的自由泳");
            }
        });
    }

    public static void go(Swimming s){
        System.out.println("开始");
        s.swim();
        System.out.println("结束");
    }
}

class Student implements Swimming{

    @Override
    public void swim() {
        System.out.println("学生快乐的自由泳");
    }
}

interface Swimming{
    void swim();
}

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

package com.pikaqiu.d6_innerclass_anonymous;

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,"你是傻子");
//            }
//        });

        btn.addActionListener(e -> JOptionPane.showMessageDialog(win,"说爱我"));

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

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

三、常用API

1.Object

Object类的作用:1.一个类要么默认继承了Object类,要么间接继承了Object类,Object类是Java中的祖宗类;2.Object类的方法是一切子类可以直接使用的

toString存在的意义:父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息 

equals存在的意义:父类equals方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则

package com.pikaqiu.d7_api_object;

import java.util.Objects;

public class Student { //extends Object
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

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

package com.pikaqiu.d7_api_object;

public class Test {
    public static void main(String[] args) {
        Student s = new Student("皮卡丘",18);
        //System.out.println(s.toString());
        //直接输出对象变量,默认可以省略toString调用
        System.out.println(s);
    }
}

package com.pikaqiu.d7_api_object;

public class Test2 {
    public static void main(String[] args) {
        Student s1 = new Student("皮卡丘",18);
        Student s2 = new Student("皮卡丘",18);
        System.out.println(s1.equals(s2));
        System.out.println(s1 == s2);
    }
}

2.Objects

Objects类是Object的子类,Objects类是从JDK 1.7开始之后才有的

Objects的equals方法与Object里的equals方法比较的结果是一样的,但是更安全

package com.pikaqiu.d8_api_objects;

import java.util.Objects;

public class Test {
    public static void main(String[] args) {
        String s1 = null;
        String s2 = new String("pikaqiu");
        //System.out.println(s1.equals(s2)); //错误,会出现空指针异常

        /**
         *  public static boolean equals(Object a, Object b) {
         *         return (a == b) || (a != null && a.equals(b));
         *     }
         */
        System.out.println(Objects.equals(s1, s2)); //更安全,结果更准确

        System.out.println(Objects.isNull(s1)); //true
        System.out.println(s1 == null);
    }
}

 3.StringBuilder

StringBuilder是一个可变的字符串类,我们可以把它看成是一个对象容器

作用:提高字符串的操作效率,如拼接、修改等

​​​​​​​

package com.pikaqiu.d9_api_stringbulider;

public class StringBuilderDemo1 {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append("a");
        System.out.println(sb); //a

        StringBuilder sb1 = new StringBuilder();
        sb1.append("a").append("b").append("c").append("就这");
        System.out.println(sb1); //abc就这

        //反转
        sb1.reverse();
        System.out.println(sb1); //这就cba

        //求长度
        System.out.println(sb1.length());

        //注意:StringBuilder只是拼接字符串的手段,效率好
        //最终结果还是要恢复成String类型
        StringBuilder sb2 = new StringBuilder();
        sb2.append("123").append("456");
        //恢复成String
        String rs = sb2.toString();
        check(rs);
    }

    public static void check(String data){
        System.out.println(data);
    }
}

案例:

package com.pikaqiu.d9_api_stringbulider;

public class StringBuilderTest2 {
    public static void main(String[] args) {
        int[] arr1 = null;
        System.out.println(toString(arr1));

        int[] arr2 = {11,22,33,44};
        System.out.println(toString(arr2));

        int[] arr3 = {};
        System.out.println(toString(arr3));
    }

    public static String toString(int[] arr){
        if(arr != null){
            StringBuilder sb = new StringBuilder("[");
            for (int i = 0; i < arr.length; i++) {
                sb.append(arr[i]).append(i == arr.length - 1 ? "" : ",");
            }
            sb.append("]");
            return sb.toString();
        }else {
            return null;
        }
    }
}

4.Math

Math类包含执行基本数字运算的方法,Math类没有提供公开的构造器

package com.pikaqiu.d10_math;

public class MathDemo {
    public static void main(String[] args) {
        //取绝对值,返回正数
        System.out.println(Math.abs(-10.5)); //10.5

        //向上取整
        System.out.println(Math.ceil(4.3)); //5.0
        //向下取整
        System.out.println(Math.floor(3.2)); //3.0

        //求指数次方
        System.out.println(Math.pow(3,2)); //3^2=9

        //四舍五入
        System.out.println(Math.round(4.52)); //5

        System.out.println(Math.random()); //0.0-1.0中的随机一个数(包前不包后)

        //拓展:3-9直接的随机整数
        //[0-6] + 3
        int data = (int)(Math.random() * 7) + 3;
        System.out.println(data);
    }
}

5.System

System的功能是通用的,都是直接用类名调用即可,所以System不能被实例化

package com.pikaqiu.d11_system;

import java.util.Arrays;

public class SystemDemo {
    public static void main(String[] args) {
        System.out.println("程序开始~~~");

        //System.exit(0); //JVM终止

        //计算机认为时间起源:返回1970-1-1 00:00:00 走到此刻的总的毫秒值(时间毫秒值)
        long time = System.currentTimeMillis();
        System.out.println(time);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            System.out.println(i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println((endTime - startTime) / 1000.0 + "s");

        //数组拷
        /**
         * arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);
         * 参数一:被拷贝的数组
         * 参数二:从哪个索引位置开始拷贝
         * 参数三:复制的目标数组
         * 参数四:粘贴位置
         * 参数五:拷贝元素的个数
         */
        int[] arr1 = {10,20,30,40,50,60};
        int[] arr2 = new int[5]; //[0,0,40,50,60]
        System.arraycopy(arr1,3,arr2,2,3);
        System.out.println(Arrays.toString(arr2));

        System.out.println("程序结束~~~");
    }
}

 6.BigDecimal

用于解决浮点型运算失真的问题

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮卡丘√

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值