初识JAVA10:多态、抽象类和方法、接口、设计模式

JAVA面向对象04

  • 面向对象
  • 多态
    • 引用类型数据的向上和向下转型
  • 抽象类和抽象方法
  • 接口
  • 设计模式
    • 单例模式
    • 代理模式
    • 简单工厂模式

面向对象

多态

面向对象的三大特征之一

​ 多种形态->多种表现形式

多态的最终体现:

​ 父类的引用指向子类的对象

多态的前提:

​ 继承关系

​ 实现关系

多态的使用:

​ 需要配合方法的重写才有意义

​ 当多态调用时候,会调用子类中的重写方法

​ 多态引用对子类非重写内容不可见

多态调用成员特点:

​ 成员变量:

​ 编译运行看父类|左边|类型

​ 成员方法:

​ 编译看父类,运行找子类

​ 编译看左边,运行找右边

​ 编译看类型,运行找对象

优点:

​ 减少耦合性,增加灵活性,便于后期维护

package com.xxx.learn.tostringdemo;

public class UserInfo {
    private String name;
    private int age;
    private int id;

    public UserInfo(){
    }

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

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

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

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public int getId() {
        return id;
    }

    public String toString(){
        return "姓名:"+this.name+"\n年龄:"+this.age+"\n学号:"+this.id+"\n";
    }

    public void print(){
        System.out.println("我是User");
    }
}
package com.xxx.learn.tostringdemo;

public class StudentInfo extends UserInfo{
    private String className;

    public StudentInfo(){
    }

    public StudentInfo(String name,int age,int id,String className){
        super(name,age,id);
        this.className = className;
    }

    public String getClassname() {
        return className;
    }

    public String toString(){
        return super.toString()+"班级:"+this.className;
    }

    public boolean equals(Object obj){
        if(this == obj){
            return true;
        }
        if(obj instanceof StudentInfo){
            String name = ((StudentInfo) obj).getName();
            String className = ((StudentInfo)obj).getClassname();

            return (this.getName().equals(name) && this.getClassname().equals(className) && this.getAge() == ((StudentInfo)obj).getAge() && this.getId() == ((StudentInfo)obj).getId());
        }
        return false;
    }

    public void print(){
        System.out.println("我是Student");
    }
}
package com.xxx.learn.tostringdemo;

public class ToStringDemo {
    public static void main(String[] args) {
        StudentInfo si1 = new StudentInfo("张三",20,10000,"高一三班");
        StudentInfo si2 = new StudentInfo("张",20,10000,"高一三班");
        UserInfo ui = new UserInfo("张",20,10000);

        //多态,将子类对象赋值给父类的引用
        UserInfo ui1 = new StudentInfo("张三",20,10000,"高一三班");
        System.out.println(si1);
        System.out.println(si2);

        System.out.println(si1.equals(si2));
        //ui1对象属于StudentInfo类,所以可以判断对象的内容是一致的
        System.out.println(si1.equals(ui1));
        //此时ui调用的为自己的print方法
        ui.print();
        si1.print();
        //多态的状态下可以实现父类的引用调用子类重写的方法
        ui1.print();
    }
}
/*
输出:

姓名:张三
年龄:20
学号:10000
班级:高一三班
姓名:张
年龄:20
学号:10000
班级:高一三班
false
true
我是User
我是Student
我是Student
*/

引用类型数据的向上和向下转型

基本数据类型 :

​ 自动类型提升 : 小–>大

​ int i = ‘a’;

​ 强制类型转换 : 大–>小

​ byte b = (byte)i;

​ 转型:

​ 引用数据类型:

​ 父类->大

​ 子类->小

​ 向上转型: 小->大

​ Person p = new Student();

​ 向下转型: 大->小

​ Student s = (Student)p;

通过多态的引用调用子类中新增的内容时候,需要向下转型

注意:

​ 对象向上转型后再使用向下转型,不能直接父类对象强制转型为子类引用,否则转型后通过子类引用调用子类方法或父类方法会报错

​ 向下转型时候,如果类型不注意,就有可能出现ClassCastException类型转换异常

instanceof 运算符–>避免遇到类型转换异常

​ 引用 instanceof 类型 : 判断前面的引用是否是指向后面类型的对象|子类对象->是true | 不是false

抽象类和抽象方法

抽象方法:被abstract修饰的方法

​ 没有方法体

​ 要求定义在抽象类中

抽象类:被abstract修饰的类

父类:

​ 具体的父类:普通的类,类中所有的方法必须存在实现(方法体)

​ 抽象的父类:抽象类,可以存在具体方法,可以存在抽象方法

抽象类特点

​ 1.抽象类中可以存在具体方法,可以存在抽象方法

​ 可以存在成员变量,构造器…

​ 2.抽象类不能实例化(不饿能创建对象)

​ 3.一个抽象方法必须被重写,重写可以为抽象方法定义方法体

​ 4.抽象类的使用:通过具体子类的对象使用

​ 具体的子类:重写了所有抽象方法+按需新增

​ 抽象的子类:按需重写抽象方法+按需新增

​ 5.一个抽象方法一旦被重写,后续是否需要重写根据实现

​ 6.abstract关键字不能与private,final,static,native一起使用

package com.xxx.learn.abstractdemo;

public class AbstractDemo {
    public static void main(String[] args) {
        CarZi1 cz1 = new CarZi1("玛莎拉蒂");
        cz1.start();
        cz1.stop();

        //'CarZi2' is abstract; cannot be instantiated
        //CarZi2 cz2 = new CarZi2("玛莎拉蒂");
    }
}

abstract class CarAbstract{
    public String brand;

    public CarAbstract(){}

    public CarAbstract(String brand){
        this.brand = brand;
    }

    public abstract void start();

    public void stop(){
        System.out.println(brand+"停下了");
    }
}


class CarZi1 extends CarAbstract{

    public CarZi1(){}

    public CarZi1(String brand) {
        super(brand);
    }

    //具体子类继承抽象父类,需要将抽象父类中的抽象方法全部实现
    public void start(){
        System.out.println(brand+"启动了");
    }
}

abstract class CarZi2 extends  CarAbstract{
    public CarZi2(){}

    //抽象子类继承抽象父类不需要实现父类中的抽象方法
}

接口

​ 特殊的抽象类

​ 是一种引用数据类型

​ 功能的集合(抽象方法的集合)

​ 继承与实现:

​ 类的继承:

​ 子类一旦继承父类,就有权使用父类中的内容,拿过来就可以直接使用

​ 接口的实现:

​ 实现类一旦实现一个接口,需要对接口中的抽象功能进行实现->重写,然后才能使用

​ 侧重点不同

​ 类只能单继承,接口可以多实现

​ 接口便于后期维护,更加灵活

​ 接口实现解耦(高内聚低耦合)

​ 定义开发规范

​ 推荐使用接口,但是接口不能完全替代父类

​ 定义:

​ class 类

​ interface 接口

​ jdk7及以前:

​ 公共的静态的常量 public static final->默认可以任意省略

​ 公共的抽象的方法 public abstract->默认可以任意省略

​ jdk8及之后:

​ 接口中可以定义被static或被default修饰的具体方法

​ 1.静态方法

​ 只能跟随接口名.使用,不能在实现类对象调用和重写

​ 2.默认方法

​ 跟随实现类对象调用,可以在实现类中进行重写

​ 接口的使用

​ 1.不能实例化

​ 2.接口需要被实现 通过implements关键字进行实现

​ 3.根据实现类对象使用

​ 具体实现类:重写所有的抽象方法+按需新增

​ 抽象实现类:按需重写抽象方法+按需新增

​ 4.类只能单继承,类可以实现多接口,需要重写多个抽象方法

​ 5.类与接口之间只能是类实现接口,可以多实现

​ 6.接口与接口之间,可以多继承

​ 7.一个类需要先继承后实现

package com.xxx.demo.interfacedemo;

public class InterfaceDemo {
    public static void main(String[] args) {
        Computer computer = new Computer();
        Mouse mouse = new Mouse();
        computer.run(computer.check());
        //实现类调用接口中的default方法
        computer.write();
        computer.read();
        //接口中static修饰的具体方法只能通过接口名.调用
        Usb.initialize();
        //接口的多态
        computer.startUseUSB(mouse);    //computer.startUseUSB(Usb usb);
        computer.stopUseUSB(mouse);
    }
}


interface Memory{
    boolean memory();
}

interface Cpu{
    boolean cpu();
}

interface Disk{
    boolean disk();

    //jdk8及以后可以在接口中声明被default修饰的具体方法
    default void write(){
        System.out.println("正在向硬盘写入数据...");
    }

    default void read(){
        System.out.println("正在读取硬盘数据...");
    }
}

interface Power{
    boolean power();
}

interface Usb{
    //jdk8及以后可以在接口中声明被static修饰的具体方法
    static void initialize(){
        System.out.println("驱动正在初始化...");
    }
    void start();
    void stop();
}

//接口可以多继承接口
interface MainBoard extends Memory,Cpu,Disk,Power {
    boolean check();
}

//具体类实现接口的所有方法
class  Computer implements MainBoard{
    @Override
    public boolean cpu() {
        System.out.println("cpu成功安装");
        return true;
    }

    @Override
    public boolean memory() {
        System.out.println("内存成功安装");
        return true;
    }

    @Override
    public boolean disk() {
        System.out.println("硬盘成功安装");
        return true;
    }

    @Override
    public boolean power() {
        System.out.println("电源成功安装");
        return true;
    }

    @Override
    public boolean check(){
        if(cpu()&&memory()&&disk()&&power())
            System.out.println("硬件自检通过!");
        return true;
    }

    public void run(boolean flag){
        if(flag) System.out.println("电脑启动成功!");
    }

    //接口的多态,将实现类对象给接口的引用,接口的引用调用实现类中重写的方法
    public void startUseUSB(Usb usb){
        usb.start();
    }

    public void stopUseUSB(Usb usb){
        usb.stop();
    }

}


class Mouse implements Usb{


    @Override
    public void start() {
        System.out.println("开始使用鼠标");
    }

    @Override
    public void stop() {
        System.out.println("停止使用鼠标");
    }
}

设计模式

单例模式

单例模式:某个类型只能拥有单个实例->单例模式

实现方式:

​ 1.饿汉式:在类第一次加载完成之后,就创建实例,线程是安全的,同步的,一般效率较低

​ 2.懒汉式:在调用的时候,创建实例,线程是不安全的,不同步的,一般效率较高

步骤:

​ 1.私有的构造器

​ 2.私有的静态的该类的引用->指向创建好的那个对象

​ 3.公共的静态的访问方式->返回提供一个当前类型的实例

package com.xxx.learn.singledemo;

public class SingleDemo {

    public static void main(String[] args) {
        System.out.println(SingleE.test);   //此时SingleE类已被加载,对象已经被创建
        System.out.println(SingleE.getSh());
        SingleE se = SingleE.getSh();
        System.out.println(se);
        System.out.println(SingleE.getSh());

        SingleL sl = SingleL.getSl();
        System.out.println(sl);
        System.out.println(SingleL.getSl());
    }
}


//饿汉式

class SingleE{
    static {
        System.out.println("SingleE被加载");
    }

    private static SingleE se = new SingleE();

    private SingleE(){}

    public static SingleE getSh(){
        return se;
    }

}

//懒汉式

class SingleL{

    private static SingleL sl = null;

    private SingleL(){}

    public static SingleL getSl() {
        if(sl == null) {
            return sl = new SingleL();
        }
        return sl;
    }
}

代理模式

​ 静态代理:

​ 真实角色

​ 代理角色

​ 条件:

​ 真实角色与代理角色要求实现相同的接口

​ 代理角色需要持有真实角色的引用–>通过属性来维护代理行为

​ 减少与真实角色的沟通,让程序便于后期维护

package com.xxx.learn.proxydemo;

public class ProxyDemo {
    public static void main(String[] args) {
        //项目经理
        Manager manager  = new Manager();
        //Hr
        Hr hr = new Hr(manager);
        //开始招人
        hr.addUser();
    }
}

//招人
interface AddUser{
    void addUser();
}

//真实角色 项目经理
class Manager implements AddUser{

    @Override
    public void addUser() {
        System.out.println("录用了...");
    }
}


//代理角色
class Hr implements AddUser{
    //管理者
    Manager manager;

    public  Hr(Manager manager){
        this.manager = manager;
    }

    @Override
    public void addUser() {
        System.out.println("发布招聘信息...");
        System.out.println("预约面试");
        //项目经理面试
        manager.addUser();
        System.out.println("录用成功..谈薪资...");
    }
}

简单工厂模式

​ 抽象产品角色:具体产品角色实现的接口|继承的父类

​ 具体产品角色:抽象产品角色的实现类

​ 工厂角色

你可能感兴趣的:(说明,学习,多态,抽象类,设计模式,java)