Java抽象类与接口

文章详细阐述了Java中的final关键字的用法,包括属性和方法的不可变性以及类的不可继承性。接着讨论了向下转型的概念,说明其在向上转型过程中的作用和风险。然后介绍了抽象类,作为多态的核心,强调了抽象方法和抽象类的特性。此外,文章还提到了接口的使用,强调了接口的优先原则,并通过例子展示了接口如何表示规范和能力。最后,文中提到了JDK中的Comparable接口及其在排序中的应用。
摘要由CSDN通过智能技术生成

0、回顾

(1)final:终结器
        被final修饰的属性值不能改(基本类型就是数值不变,引用类型保存的地址值不变)
        被final修饰的方法不能重写
        被final修饰的类不能有子类
(2)向下转型:
        ①语法︰ 子类名称 子类引用 = (子类名称) 父类引用;

Dog dog = (Dog) animal;

        · 要求∶要发生向下转型首先需要发生向上转型,父类引用必须要和当前子类的对象建立联系。即animal实际上指向的就是Dog类的对象

Animal animal = new Dog(0);

        · 向下转型存在类型转换异常的风险,因此要使用向下转型可以借助instanceof关键字只有这个关键字返回true,再使用向下转型:
        引用名称 instanceof 类名称 -> true或false,表示该引用是否指向一个类的对象
        ②向下转型一般用在向上转型的过程中,需要调用某些子类独有的方法或属性

Animal animal = new Dog();

        · 通过animal引用能够调用哪些方法,要看Animal父类中有哪些方法
        · 至于调用方法到底调用的是子类中的方法还是父类中的方法,要看new在哪。若产生的是子类对象且该子类覆写了调用方法,则一定调用子类覆写后的方法
        · 若需要调用子类中独有的方法,就需要还原这个animal引用为子类引用,这就是向下转型的应用场景:和向上转型搭配使用
        ③向上转型∶参数统一化,降低圈复杂度(减少大量的if-else语句)
向下转型:在向上转型过程中调用某些子类独有的方法

1、要实现多态,最核心的依赖于继承与方法重写,关键问题在于父类无法强制要求子类重写方法。因此,就该定义抽象类

(1)抽象类:

        普通类的超集,只是比普通类多了一些[0~N]抽象方法而已。
①使用关键字abstract来定义抽象类与抽象方法

abstract class A{ //抽象类
    public abstract void testA(); //抽象方法(只声明)
}

        · 只要类使用abstract来定义,这个类无论是否包含抽象方法,都是抽象类。
        · 抽象类无法直接实例化对象。因为这个类本身就是一个抽象的概念,不存在具体对象
        · 抽象类必须有子类,子类继承抽象类后必须要覆写所有的抽象方法(前提:该子类是普通类,若该子类是抽象类,可以不覆写抽象方法)
        · 抽象方法使用abstract来定义,只有方法声明,没有方法体的方法称为抽象方法。只有在子类覆写该方法时,该方法才有了具体实现,在抽象类中,该方法只有声明
*在Java中,没有方法体的方法一定是抽象方法?
        答案错!Java中还有一类方法没有方法体,只有方法声明,使用native关键字声明,这种方法称为本地方法本地方法指的是,Java调用C++实现的代码,具体的方法实现在C++代码中,Java只是调用。(JVM:本身就是C++实现的,有大量的C++函数,Java直接调用)。JNDI平台,借助这个开发平台,可以实现在Java中调用C++的代码。Oracle(Java公司)未来JVM可以直接运行C++的项目。
(2)若有抽象类A其中有抽象方法x(),抽象类B继承抽象类A其中有抽象方法y(),则普通类C继承B时,必须要把x()、y()都覆写,
(3)抽象类只是比普通类多了一些抽象方法而已,抽象类的内部仍然可以存在构造方法与普通方法
虽然抽象类无法直接实例化对象,子类在产生对象时,仍然满足继承的原则,先调用父类的构造方法实例化父类,然后再调用子类构造

 2、要对子类进行一些强制性的方法覆写要求,会用到抽象类。但是即便是抽象类,子类也仍然存在单继承局限的要求,以及必须满足is a原则,继承的类之间,是一个垂直结构的树形关系。

3、接口∶之后能使用抽象类也能使用接口实现的场景下,优先考虑使用接口实现。接口优先原则

(1)定义︰

        接口中只存在全局常量与抽象方法(JDK8之前),在Java中,接口使用interface关键字来定义.
        · 接口当中的成员变量默认是:public static final
        · 接口当中的成员方法默认是:public abstract
(2)接口的命名规范:

        使用大写的l开头
(3)接口的子类,称为实现接口
        ①子类要实现接口,使用 implements 关键字来表示子类实现(约等于继承)接口,子类必须覆写接口中的所有抽象方法(前提∶子类是普通类)
        ②子类的命名∶以父类接口名称开头,以impl结尾。例如 MessageImpl : 一眼看上去就知道是IMessage接口的子类
        ③接口中只能定义全局常量与抽象方法,不能存在构造方法,不能存在成员变量,因此接口是一个更加"纯粹"的抽象类。接口无法直接实例化对象,需要通过子类向上转型为其实例化
(4)接口使用原则:
        ①由于接口中只存在抽象方法与全局常量,因此,在接口定义中,以下关键字统统都可以省略,且在阿里编码规约中明确表示,以下关键字不要出现在接口的定义中
                · public //描述属性
                · static final //描述常量
                · abstract //描述抽象方法
        ②子类可以同时实现多个父接口(打破抽象类的单继承局限~~)
实现多个父接口,用逗号分隔。若子类同时实现了多个父接口,则必须覆写这些接口中的所有抽象方法(前提︰子类是普通类)
        ③当子类同时需要实现多个父接口,以及继承一个抽象类时,请先使用extends继承一个类,而后使用implements实现多个接口

class MessageImplNew extends News implements IMessage{
    //覆写方法
}

                · 按顺序,先写extends类,再写implement接口
        ④接口不能使用extends继承类,但是接口可以使用extends来继承父接口,而且可以继承多个

4、抽象类与接口比较

 

 5、接口的应用场景

(1)接口表示标准或规范(以USB为例)
        ①USB接口就是表示一种规范/标准

public interface USB {
    void setUp(); //安装驱动
    void work(); //正常工件
}

②鼠标

public class Mouse implements USB{
    @Override
    public void setup(){
        System.out.print1n("安装鼠标驱动中..");
    }
    @Override
    public void work() {
        system.out.println("鼠标正常工作~");
    }
}

③键盘

public class KeyBoard implements USB{
    @Override
    public void setup() {
        system.out.println("安装键盘驱动中..");
    }
    @Override
    public void work() {
        system.out.println("键盘正常工作~");
    }
}

④模拟USB插槽(电脑对外提供的方法)

public class Computer {
    public void plugIn(USB usb){
        usb.setUp();
        usb.work();
    }
    public static void main(String[] args) {
        Computer computer = new Computer();
        Mouse mouse = new Mouse();
        computer.plugIn(mouse); //需要将鼠标对象连接到电脑上
        KeyBoard keyBoard = new KeyBoard();
        computer.plugIn(keyBoard); //需要将键盘对象连接到电脑上
    }
}

(2)接口表示一种能力/行为
①Cat就具备在地上跑的能力

public class Cat extends Animal implements IRun{...}

②Dog就具备了地上跑,水里游的能力

public class Dog extends AnimaL implements IRun,ISwim{...}

③Duck具备地上跑,水里游,天生飞的能力

public class Duck extends Animal implements IRun,ISwim,IFLy{...}

④可以方便调用不同的方法

public static void main(String[] args){
    Dog dog = new Dog("66",7);
    Cat cat = new Cat("元宝",7);
    Robot robot = new Robot();
    fun(dog);
    fun(cat);
    fun(robot);
}

//调用传入对象的run方法
public static void fun(IRun runObj) {
    runObj.run();
}

 6、JDK中的常用接口

(1)java.lang.Comparable接口compareTo方法

int[] nums = {1,5,3,2,6,8,9,7};
Arrays.sort(nums); //对nums,数组排序

· 此时可以正常排序

student[] students = new Student[3];
students[e] = new Student("铭哥",65);
students[1] = new Student("子健",90);
students[2] = new Student("云超",77.8);
Arrays.sort( students);

(2)当传入对象时自定义类时则无法完成排序,需要在Student类里覆写compareTo方法来实现排序
①原本内容

public int compareTo(Object o){
    return 0;
}

        · return < 0 :表示当前对象 < 传入对象o
        · return == 0 :表示当前对象 == 传入对象o
        · return > 0 ∶表示当前对象 > 目标对象o
②覆写后

@override
public int compareTo(Object o) {
    if (this == o){ //判断传入对象是否当前对象是同一个引用
        return 0;
    }else if(!(o instanceof Student)) {
        return -1; //判断是否是Student类型
    }else { //此时o一定是Student类型,且和当前对象不是同一个Student对象
        Student stu = (student) o;
        return (int)(this.score - stu.score);
    }
}

· 此时将传入对象按照成绩升序排序(降序的话,把return 后面的改一下)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值