Java——抽象类和接口

一、 抽象类

1. 什么是抽象类

在面向对象的概念中,
所有的对象都是通过类来描绘的,
但是反过来,并不是所有的类都是用来描绘对象的,
如果一个类中没有包含足够的信息来描绘一个具体的对象,
这样的类就是抽象类。比如:
在这里插入图片描述

在这里插入图片描述
在打印图形例子中, 我们发现,
父类 Shape 中的 draw 方法好像并没有什么实际工作,
主要的绘制图形都是由 Shape 的各种子类的 draw 方法来完成的.
像这种没有实际工作的方法,
我们可以把它设计成一个 抽象方法(abstract method),
包含抽象方法的类我们称为 抽象类(abstract class).

// 抽象类:被abstract修饰的类
public abstract class Shape {
    // 抽象方法:被abstract修饰的方法,没有方法体 
    abstract public void draw();
    abstract void calcArea();
     // 抽象类也是类,也可以增加普通方法和属性 
    public double getArea(){
        return area;
    }
    protected double area;    // 面积
 }

2. 抽象类的特性

抽象类也是类,
内部可以包含普通方法和属性,
甚至构造方法。
抽象类也是类,也可以增加普通方法和属性

抽象类不能直接实例化对象。

抽象方法不能是 private 的。

抽象方法没有加访问限定符时,默认是public。

抽象方法不能被final和static修饰,因为抽象方法要被子类重写。

抽象类必须被继承,
并且继承后子类要重写父类中的抽象方法,
否则子类也是抽象类,
必须要使用abstract 修饰。

抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类。

抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量。

二 、 接口

接口就是公共的行为规范标准,
大家在实现时,只要符合规范标准,就可以通用。

在Java中,接口可以看成是:
多个类的公共规范,是一种引用数据类型。

1. 语法规则

创建接口时, 接口的命名一般以大写字母 I 开头.

接口的命名一般使用 “形容词” 词性的单词.

阿里编码规范中约定, 接口中的方法和属性不要加任何修饰符号, 保持代码的简洁性.

public interface 接口名称{
    // 抽象方法
    public abstract void method1();   // public abstract 是固定搭配,可以不写 
    public void method2();
    abstract void method3();
    void method4();

    // 注意:在接口中上述写法都是抽象方法,跟推荐方式4,代码更简洁

2. 接口使用

接口不能直接使用,
必须要有一个"实现类"来"实现"该接口,
实现接口中的所有抽象方法。

子类和父类之间是extends 继承关系,
类与接口之间是 implements 实现关系。

public  class 类名称 implements 接口名称{ 
    // ...
}
// USB接口
public interface USB { 
    void openDevice(); 
    void closeDevice();
}


// 鼠标类,实现USB接口
public class Mouse implements USB { 
    @Override
    public void openDevice() {
	System.out.println("打开鼠标"); 
}

    @Override
    public void closeDevice() { 
        System.out.println("关闭鼠标"); 
    }

    public void click(){ 
        System.out.println("鼠标点击"); 
    }

// 键盘类,实现USB接口
public class KeyBoard implements USB { 
    @Override
    public void openDevice() { 
        System.out.println("打开键盘");
    }

    @Override
    public void closeDevice() { 
        System.out.println("关闭键盘"); 
    }

    public void inPut(){ 
        System.out.println("键盘输入"); 
    }

// 笔记本类:使用USB设备
public class Computer {
    public void powerOn(){ 
        System.out.println("打开笔记本电脑"); 
    }

    public void powerOff(){ 
        System.out.println("关闭笔记本电脑"); 
    }

    public void useDevice(USB usb){ 
        usb.openDevice();
        if(usb instanceof Mouse){
            Mouse mouse = (Mouse)usb; 
            mouse.click();
        }else if(usb instanceof KeyBoard){ 
            KeyBoard keyBoard = (KeyBoard)usb; 
            keyBoard.inPut();
        }
        usb.closeDevice();
    }
 }


// 测试类:
public class TestUSB {
    public static void main(String[] args) { 
        Computer computer = new Computer(); 
        computer.powerOn();

        // 使用鼠标设备 
        computer.useDevice(new Mouse());
        // 使用键盘设备 
        computer.useDevice(new KeyBoard());
                computer.powerOff(); 
    }
 }

3. 接口特性

接口类型是一种引用类型,但是不能直接new接口的对象。

接口中每一个方法都是public的抽象方法,
即接口中的方法会被隐式的指定为 public abstract
(只能是 public abstract,其他修饰符都会报错)。

接口中的方法是不能在接口中实现的,只能由实现接口的类来实现。

重写接口中方法时,不能使用default访问权限修饰。

接口中可以含有变量,
但是接口中的变量会被隐式的指定为 public static final 变量。

接口中不能有静态代码块和构造方法。

接口虽然不是类,
但是接口编译完成后字节码文件的后缀格式也是.class 。

如果类没有实现接口中的所有的抽象方法,
则类必须设置为抽象类。

jdk8中:接口中还可以包含default方法。

4. 实现多个接口

一个类可以实现多个接口。

一个类实现多个接口时,
每个接口中的抽象方法都要实现,
否则类必须设置为抽象类。

5. 接口间的继承

在Java中,类和类之间是单继承的,
一个类可以实现多个接口,
接口与接口之间可以多继承。
即:用接口可以达到 多继承的目的。

接口可以继承一个接口, 达到复用的效果,
使用 extends 关键字。

6. 接口使用实例

给对象数组排序
class Student { 
    private String name; 
    private int score;
    public Student(String name, int score) { 
        this.name = name;
        this.score = score;
    }

    @Override
     public String toString() {
        return "[" + this.name + ":" + this.score + "]"; 
    }
}

// 再给定一个学生对象数组, 对这个对象数组中的元素进行排序(按分数降序).
Student[] students = new Student[] { 
    new Student("张三", 95),
    new Student("李四", 96),
    new Student("王五", 97),
    new Student("赵六", 92),
};

// 两个学生对象的大小关系 怎么确定? 需要我们额外指定.
让Student 类实现 Comparable 接口, 并实现其中的 compareTo 方法

class Student implements Comparable {
    private String name;
    private int score;

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


    @Override
    public String toString() {
        return "[" + this.name + ":" + this.score + "]";
    }
 

    @Override
    public int compareTo(Object o) {
        Student s = (Student)o;
        if (this.score > s.score) {
            return -1;
        } else if (this.score < s.score) {
            return 1;
        } else {
            return 0;
       }
    }
}

// compareTo 的参数是 Object , 其实传入的就是 Student 类型的对象.
然后比较当前对象和参数对象的大小关系(按分数来算).

如果当前对象应排在参数对象之前, 返回小于 0 的数字;
如果当前对象应排在参数对象之后, 返回大于 0 的数字;
如果当前对象和参数对象不分先后, 返回 0;

再次执行程序, 结果就符合预期了.


// 执行结果
[[王五:97], [李四:96], [张三:95], [赵六:92]]

7. Clonable 接口和深拷贝

三 、Object类

Object是Java默认提供的一个类。
Java里面除了Object类,所有的类都是存在继承关系的。
默认会继承Object父类。
即所有类的对象都可以使用Object的引用进行接收。

1. 获取对象信息

如果要打印对象中的内容,
可以直接重写Object类中的toString()方法。

// Object类中的toString()方法实现:
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());

}

2. 对象比较equals方法

在Java中 == 进行比较时:

如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同。

如果==左右两侧是引用类型变量,比较的是引用变量地址是否相同。

如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的:

// Object类中的equals方法
public boolean equals(Object obj) {
    return (this == obj);   // 使用引用中的地址直接来进行比较

}

class Person{
    private String name ; 
    private int age ; 
    public Person(String name, int age) {
        this.age = age ; 
        this.name = name ;
    }
    
     @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false ; 
        }
        if(this == obj) {
            return true ; 
        }
        // 不是Person类对象
        if (!(obj instanceof Person)) {
            return false ; 
        }
        
        Person person = (Person) obj ; // 向下转型,比较属性值
        return this.name.equals(person.name) && this.age==person.age ; 
    }
}

3. hashcode方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值