java抽象类+接口


前言


一、抽象类

当一个类不能完整的描述具体的对象的时候,就叫抽象类。
抽象方法没有具体实现。
定义

abstract class  Shape{//抽象类
    public abstract  void draw();//抽象方法
}

只要有抽象方法就必须定义为抽象类。抽象类中可以有普通的成员方法和成员变量。
注意:1.抽象类不能够实例化。普通类可。但是可以存在构造方法,子类实例化帮助其初始化。
2.抽象类不一定包含抽象方法。
3.当普通类继承抽象类,普通类必须重写抽象方法。(用alt+回车快捷重写)
4.抽象类存在的最大意义就是为了被继承。
5.当一个抽象类A继承一个抽象类B,此时抽象类A并不需要重写,但是当一个普通C继承了抽象A,此时需要重写所以没有重写的抽象方法。
6.抽象方法不能被final和static所修饰。
7.使之多一次编译器校验。

二、接口

对一个标准的规范。多个类的公共规范。
interface关键字。

interface   Shape{
    public  abstract void draw();
}

1.接口是使用interface来定义的。
2.接口中不能有实现的方法,但是有两种类型的方法需要注意:
2.1静态方法可以有具体实现。
2.2有default关键字修饰的也可有具体实现。(jdk8以后)
3.接口中默认是public abstract修饰的方法。
在这里插入图片描述
5.里面的成员变量默认是public static final修饰的常量。
在这里插入图片描述
不赋值报错。赋值且为静态常量
在这里插入图片描述
上面与其等价。
在这里插入图片描述
6.接口不能通过new关键字实例化。
7.类和接口使用关键字implements来关联。抽象方法必须重写,default方法可以不重写,static方法不能重写。
在这里插入图片描述
8.虽然接口不能够实例化自己,但可以向上转型。如下还是ok的。接口被编译完后也有自己独立的.class文件。
在这里插入图片描述
9.创建接口时接口的命名一般以大写的I开头。(软规定)
10.子类实现接口的方法的时候,这个方法一定要是public修饰的。(因为接口默认public abstract)
11.接口当中不能有构造方法和代码块。
12.一个类不想实现接口中的方法被定义为抽象类。

接口案例

interface  USB{
    void close();
    void open();
}
class Mouse implements USB{
    @Override
    public void open(){
        System.out.println("打开鼠标");
    }
    @Override
    public void close(){
        System.out.println("关闭鼠标");
    }
    public void click(){
        System.out.println("点击鼠标");
    }
}
class KeyBoard implements USB{
    @Override
    public void open(){
        System.out.println("键盘打开");
    }
    @Override
    public void close(){
        System.out.println("键盘关闭");
    }
    public void input(){
        System.out.println("键盘输入");
    }

}
class Computer implements USB{
    @Override
    public void open(){
        System.out.println("打开电脑");
    }
    @Override
    public void close(){
        System.out.println("关闭电脑");
    }
    public void diannao(){
        System.out.println("打游戏");
    }
    public void useDevice(USB usb){//向上转型
        usb.open();
        if(usb instanceof KeyBoard){//向下转型,使用子类特有的方法
            KeyBoard keyBoard=(KeyBoard) usb;
            keyBoard.input();
        }else if(usb instanceof Mouse){
            Mouse mouse=(Mouse) usb;
            mouse.click();
        }
        usb.close();


    }
}
public class Test04 {
    public static void main(String[] args) {
        Computer computer=new Computer();
        computer.useDevice(new Mouse());
        Computer computer1=new Computer();
        computer1.useDevice(new KeyBoard());
    }
}

在这里插入图片描述
java不支持多继承。一个类实现多接口可以解决多继承的问题。
注意:一定是先继承类然后再实现接口。只能继承一个类。可以有多个接口。
在这里插入图片描述
为什么定义接口,因为在能满足类的需求。如飞接口,不是所有的动物都会飞,所以不定义在动物类中。单独定义类也不可,因为只能继承一个类。
接口的继承:extends来继承,意味拓展接口的功能。

抽象类和接口区别:

1.抽象类的类可以不是 public abstract修饰的,而接口必须是。
2.接口中只要static final修饰的常量,而抽象类中可以有成员变量。
3.抽象类是利用extends来继承。而接口是implements来重写。
4.定义抽象类是class abstract,而接口是interface.
5.抽象类只可以继承一个,而接口可以有多个。
6.抽象类中可以有构造方法,但接口不能有。
7.接口中的权限是public,抽象类中可以有各种权限。

三、自定义类型比较

compareTo(Comparable接口)

要把学生类强转为Comparable,然后调用compareTo。需要学生和comparable建立关系,这里利用接口。没有接口无法识别compareTo.
当我们对自定义类型进行比较一定实现可比较的接口。

import java.util.Arrays;

class Student implements Comparable<Student>{
    public String name;
    public int age;
    public double score;

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
    public int compareTo(Student o){//重写 //只能实现一个比较
      return this.age-o.age;
    }
}
public class Test02 {
    public static void main1(String[] args) {
        Student [] array=new Student[3];
        array[0]=new Student("lili",34,89.2);
        array[1]=new Student("huanghuang",33,90.2);
        array[2]=new Student("zhangsan",21,22.2);
        System.out.println("排序前"+ Arrays.toString(array));
        Arrays.sort(array);//底层调用compareTo。因此要重写其方法。
        System.out.println("排序后"+ Arrays.toString(array));
    }

    public static void main(String[] args) {
        Student [] array=new Student[3];
        array[0]=new Student("lili",34,89.2);
        array[1]=new Student("huanghuang",33,90.2);
        int ret=array[0].compareTo(array[1]);
        System.out.println(ret);
    }
}

main1结果:
在这里插入图片描述
main结果:
在这里插入图片描述

自己写bubble排序

由于后面比较一定要调用compareTo,因此参数是Comparable接口数组。数组每一个元素是对象,引用与引用之间无法比较。利用compareTo进行比较。

public class Test02 {
    public static void bubbleSort(Comparable[] comparables){
            for(int i=0;i<comparables.length-1;i++){
                for(int j=0;j< comparables.length-1-i;j++){
                    if(comparables[j].compareTo(comparables[j+1])>0){
                        Comparable tmp=comparables[j];
                        comparables[j]=comparables[j+1];
                        comparables[j+1]=tmp;
                    }
                }
            }
    }

既要根据年龄比较,又要根据分数比较。

compare(Comparator接口)

能分别实现年龄和分数同时比较。只要自己单独写比较的类就可以了。更灵活,更好。

import java.util.Arrays;
import java.util.Comparator;

class Student{
    public String name;
    public int age;
    public double score;

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
class AgeComparator implements Comparator<Student>{
    public int compare(Student o1,Student o2){
        return o1.age-o2.age;
    }
}
class ScoreComparator implements  Comparator<Student>{
    public int compare(Student o1,Student o2){
        return (int)(o1.score- o2.score);
    }
}
public class Test03 {

    public static void main(String[] args) {
        Student [] array=new Student[3];
        array[0]=new Student("lili",34,55.2);
        array[1]=new Student("huanghuang",2,90.2);
        //年龄比较
        AgeComparator ageComparator=new AgeComparator();
        int ret=ageComparator.compare(array[0],array[1]);
        System.out.println(ret);
        //分数比较
        ScoreComparator scoreComparator=new ScoreComparator();
        System.out.println(scoreComparator.compare(array[0],array[1]));

    }

}

四、clone浅拷贝与深拷贝

继承Cloneable(是一个标记接口,里面没有内容,就为了使Student与clone有关联所需它),重写clone方法,并抛出异常。还要调用clone对象是object类型(是所有类的父类),需要强转。

clone浅拷贝

import java.util.Arrays;
import java.util.Comparator;
class Student implements Cloneable{
    public String name;
    public int age;
    public double score;

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
    protected Object clone() throws CloneNotSupportedException{
            return super.clone();
    }
}
public class Test01 {

    public static void main(String[] args) throws CloneNotSupportedException{
        Student student1=new Student("lili",34,55.2);
        Student student2=(Student) student1.clone();

        System.out.println(student1);
        System.out.println(student2);
    }
}


在这里插入图片描述

clone深拷贝

要将money对象拷贝,而不是仅仅Studnent拷贝。把对象包含的所有类容拷贝完。

import java.util.Arrays;
import java.util.Comparator;
class Money implements Cloneable{
    public double money;
    protected Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
}
class Student implements Cloneable{
    public String name;
    public int age;
    public double score;
    public Money m=new Money();//类作为成员变量

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
    protected Object clone() throws CloneNotSupportedException{
        Student tmp=(Student) super.clone();//克隆出的student对象给tmp
        //Money money=(Money) tmp.m.clone();//克隆money对象。
        tmp.m=(Money) this.m.clone();
        return tmp;
            //return super.clone();
    }
}
public class Test01 {

    public static void main(String[] args) throws CloneNotSupportedException{
        Student student1=new Student("lili",34,55.2);
         student1.m.money=19.9;

        Student student2=(Student) student1.clone();

        System.out.println(student1.m.money);
        System.out.println(student2.m.money);

        student1.m.money=45.3;
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);

    }
}

在这里插入图片描述

五、类中重要方法

1.object类

是所有类的父类。
可以使用object类接受所有类的对象。

2.equals方法

比较对象中的内容是否相同时一定要重写equals方法。

 public boolean equals(Object obj){
        Student student=(Student) obj;//逻辑自己写
        return age==student.age;
    }
     System.out.println(student1.equals(student2));

3.hashCode方法

hashcode和equals,每个类都要重写,自定义类型在重写时习惯写上。
一般情况下,hashCode在散列表中才有用,确定对象在散列表中的位置。

利用generate-》equals和hashcode自动生成。

 @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 && Double.compare(student.score, score) == 0 && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, score);
    }
  public static void main(String[] args) throws CloneNotSupportedException{
        Student student1=new Student("lili",34,55.2);
        Student student2=new Student("lili",34,55.2);
        System.out.println(student1.equals(student2));
        System.out.println(student1.hashCode());//哈希码,对象的位置
        System.out.println(student2.hashCode());
    }

在这里插入图片描述


总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值