d10(104-112)-勇敢开始Java,咖啡拯救人生

本文详细解析了Java中的多态概念,包括其在继承和实现中的表现,以及类型转换注意事项。还介绍了抽象类、接口的特点、使用场景和内部类(成员、静态、局部和匿名)的概念及其应用。
摘要由CSDN通过智能技术生成

目录

多态[面向对象的三大特征:封装 继承 多态]polymorphism

多态的好处

多态下的类型转换问题

注意事项

final关键字

注意事项

常量

抽象类abstract

好处

运用场景

接口interface

好处

接口中新增的三种方法:

接口的多继承

内部类[类中五大成分:成员变量、方法、构造器、内部类、代码块]

4、匿名内部类


多态[面向对象的三大特征:封装 继承 多态]polymorphism

多态是在继承/实现情况下的一种现象,表现为:对象多态、行为多态

例如:p1为父类,p2 extends p1,p3 extends p1

        p1 p = new p2();

        p1 pp = new p3();

编译看左边,执行看右边 例如:p.run();        它的左边是p1,右边是p2 -> 行为多态

对于对象,编译、执行都看左边 例如:p.name;        打印的仍是p1对其的赋值,而不是p2

因此,多态的前提:有继承/实现关系;存在父类引用子类对象;存在方法重写

多态的注意事项:多态是对象、行为的多态,Java中的属性(成员变量)不谈多态

多态的好处

在多态形式下,右边对象是解耦合的,更便于扩展的维护 [紧耦合就很难修改]

可以使用父类类型的变量作为形参,可以接收一切子类对象 [某方法可以被多类对象使用,因为可以用父类做形参]

问题:多态下不能使用子类的独有功能。[因为编译看左边,左边父类没有子类独有功能]

多态下的类型转换问题

自动类型转换 父类 变量名 = new 子类();

强制类型转换 子类 变量名 = (子类) 父类变量

注意事项

存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错哦

运行时,如果发现对象的真实类型与强转后的类型不同,就会报类型转换异常ClassCastException的错误出来

因此,使用instanceof关键字,判断当前对象的真实类型,再强转

例如:p1为父类,p2 extends p1

        p1 p = new p2();

        if(p instanceof p2){

                p2 ppp = (p2) p; // 强转

        }

final关键字

修饰类:该类则为最终类,不能被继承了

修饰方法:最终方法,不能被重写了

修饰变量:该变量只能被赋值一次[变量:1、局部变量 2、成员变量 2.1、静态成员变量 2.2、实例成员变量]

public static final 常量

注意事项

final修饰基本类型变量,变量存储的数据不能改变

final修饰引用类型变量,变脸存储的地址不能改变,但地址所指向对象的内容可以改变

常量

用于记录系统的配置信息

static final 常量; 常量名用大写英文字母,下划线连接单词

好处:代码可读性更好,可维护性更好;程序编译后,常量会被“宏替换”,出现常量的地方会被替换为其记住的字面量,这样可以保证使用常量和使用字面量的性能是一样的

抽象类abstract

abstract修饰类 -> 抽象类

abstract修饰方法 -> 抽象方法        只有签名,没有方法体

抽象类不一定有抽象方法,有抽象方法的类一定是抽象类

抽象类可以有类有的成员(成员变量、方法、构造器)

抽象类的主要特点:抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现,故父类 变量名 = new 子类();

一个类继承抽象类,要重写抽象类的所有抽象方法,否则这个类也必须被定义为抽象类

好处

父类知道每个子类都要做的某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,可以更好的支持多态。[感觉就是父类定义一个模板,子类去挨个填充]

运用场景

解决方法中存在重复代码的问题:

1、定义抽象类

2、在里面定义两个方法:一是模板方法:把相同代码放进去;二是抽象方法,具体实现交给子类

建议用final修饰模板方法[不被子类重写]

接口interface

只能由成员变量和成员方法,其他什么都不能有

public interface 接口名{
    // 成员变量(常量)
    // 成员方法(抽象方法)
}

类和接口是同级的,因此要在package里新建class中选interface而不是class

直接写String 变量名 = ...;就行,会默认是常量,用大写英文单词,下划线连接哈

抽象方法也直接写签名就行,默认是抽象方法,不能写方法体哦

接口不能创建对象,接口是用来被类实现implement的,实现接口的类被称为实现类

修饰符 class 实现类 implements 接口1,接口2,接口3,...{}

一个类可以实现多个接口,实现类实现多个接口,必须重写完全部接口的全部抽象方法,否则实现类需定义成抽象类

好处

弥补了类单继承的不足(extends 只能继承一个),一个类可以实现多个接口;让程序可以面向接口编程,这样可以灵活方便切换各种业务实现

例子:两种方案实现某功能,只需修改选择哪个实现类

StudentOperator[接口]

package cn.ptz.interface_demo;

import java.util.ArrayList;

public interface StudentOperator {
    void printAllInofo(ArrayList<Student>students);
    void printAverageScore(ArrayList<Student>students);
}

StudentOperatormpl1[实现类1]第一个方案

package cn.ptz.interface_demo;

import java.util.ArrayList;

public class StudentOperatormpl1 implements StudentOperator{

    @Override
    public void printAllInofo(ArrayList<Student> students) {
        System.out.println("————全部全部学生信息");
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            System.out.println("姓名:"+s.getName()+",性别:"+s.getSex()+",分数:"+s.getScore());
        }
        System.out.println("————————————————————");
    }

    @Override
    public void printAverageScore(ArrayList<Student> students) {
        double allScore = 0.0;
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            allScore += s.getScore();
        }
        System.out.println("平均分:"+ (allScore) / students.size());
    }
}

StudentOperatormpl2[实现类2]第二个方案

package cn.ptz.interface_demo;

import java.util.ArrayList;

public class StudentOperatormpl2 implements StudentOperator {

    @Override
    public void printAllInofo(ArrayList<Student> students) {
        System.out.println("————全部全部学生信息");
        int count1 = 0;
        int count2 = 0;
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            System.out.println("姓名:"+s.getName()+",性别:"+s.getSex()+",分数:"+s.getScore());
            if (s.getSex() == '男'){
                count1++;
            }else {
                count2++;
            }
        }
        System.out.println("男生人数:" + count1 + ",女生人数:" + count2);
        System.out.println("————————————————————");

    }

    @Override
    public void printAverageScore(ArrayList<Student> students) {
        double allScore = 0.0;
        double max = students.get(0).getScore();
        double min = students.get(0).getScore();
        for (int i = 0; i < students.size(); i++) {
            Student s = students.get(i);
            if (s.getScore() > max){
                max = s.getScore();
            }
            if (s.getScore() < min){
                min = s.getScore();
            }
            allScore += s.getScore();
        }
        System.out.println("最高分:" + max + ",最低分:" + min);
        System.out.println("平均分:"+ (allScore-max-min) / (students.size()-2));
    }
}

ClassManager

package cn.ptz.interface_demo;

import java.util.ArrayList;

public class ClassManager {
    private ArrayList<Student> students = new ArrayList<>();
    private StudentOperator studentOperator = new StudentOperatormpl1(); //private StudentOperator studentOperator = new StudentOperatormpl2();

    public ClassManager(){
        students.add(new Student("小a",'女',80));
        students.add(new Student("小b",'男',75));
        students.add(new Student("小c",'女',95));
        students.add(new Student("小d",'男',88));

    }
    // 打印全班学生信息
    public void printInfo(){
        studentOperator.printAllInofo(students);
    }

    public void printScore(){
        studentOperator.printAverageScore(students);
    }
}

接口中新增的三种方法:

1.默认方法,必须用default修饰,默认被public修饰

   实例方法:对象的方法,必须使用实现类的对象来访问

2.私有方法:必须使用private修饰

   实例方法:对象的方法,只能在接口内部被调用

3.类方法(静态方法):必须用static修饰,默认被public修饰

   只能用接口名来调用

   增强了接口能力,更便于项目扩展和维护

接口的多继承

一个接口可以同时继承多个接口

注意事项:

1.一个接口可以同时继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承

2.一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现

3.一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的

4.一个类实现了多个接口,多个接口中存在同名的默认方法(default),可以不冲突,这个类重写该方法即可

内部类[类中五大成分:成员变量、方法、构造器、内部类、代码块]

如果一个类定义在另一个类的内部,这个类就是内部类

1、成员内部类

类中的普通成员,类似普通的成员变量、成员方法

外部类名.内部类名 对象名 = new 外部类(...).new 内部类(...);

2、静态内部类

有static修饰

外部类名.内部类名 对象名 = new 外部类.内部类();

可以直接访问外部类的静态成员,不能直接访问外部类的实例成员

3、局部内部类

定义在方法中、代码块中、构造器等执行体中

4、匿名内部类

特殊的局部内部类

匿名:不需要为这个类声明名字

其实是new 类名()

这个类名的子类

所以是创建了一个子类对象

更方便地创建一个子类对象

通常作为一个参数传输给方法

简化代码

  • 28
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值