JavaSE 基础(十) 接口

目录

前言

一. 接口

1. 接口的概念

2. 语法定义

3. 接口使用

4. 接口特性

5. 实现多个接口

6. 接口间的继承

7. 接口的使用实例

7.1 给对象数组排序

8. Clonable 接口和深拷贝 

 1.浅拷贝

 2.深拷贝

9. 抽象类和接口的区别

二. Object类

1.获取对象信息

2. 对象比较equals方法

3. hashcode方法  

后记


前言

Hi~ 你好! 

欢迎点击我的博客 : )       

这是我的学习总结,希望也能帮助到你

我的博客地址:hi~,我在这里~,欢迎关注哦,

三连不迷路,优质内容持续更新!

一. 接口

1. 接口的概念

        多个类的公共规范,是一种引用数据类型

        接口就是公共行为的规范标准,只要符合规范,就可以使用

        如usb的接口,雷电接口,插座接口等待,都遵循相应的协议

2. 语法定义

与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口
public interface TestInterface {//接口名
     String name = "s.";//接口不能被实例化
     public static final String gender= "男";//接口当中的成员默认public static final 是静态常量
    public abstract void method1();//接口当中的方法,默认为public abstract
    void method2();
//    void method3(){//接口当中的方法,不能有具体的实现
//
//    }

}

3. 接口使用

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

class Rect implements IShape{

    @Override
    public void draw() {
        System.out.println("矩形");
    }

    @Override
    public void func() {
        System.out.println("重写func()方法");
    }

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

 练习:模拟电脑和使用USB接口的硬件

public interface IUSB {//USB接口
    void openDevice();
    void closeDevice();
}
public class Mouse implements IUSB{

        @Override
        public void openDevice() {
            System.out.println("打开鼠标");
        }

        @Override
        public void closeDevice() {
            System.out.println("关闭鼠标");
        }
        public void click(){
            System.out.println("点击鼠标");
        }
}
public class KeyBoard implements IUSB{

    @Override
    public void openDevice() {
        System.out.println("打开键盘");
    }

    @Override
    public void closeDevice() {
        System.out.println("关闭键盘");
    }
    public void input(){
        System.out.println("打字");
    }
}
public class Computer {
    public void powerOn(){
        System.out.println("开机");
    }
    public void powerOff(){
        System.out.println("关机");
    }
    public void useDevice(IUSB 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();
        Mouse mouse = new Mouse();
        KeyBoard keyBoard = new KeyBoard();
        computer.powerOn();
        computer.useDevice(keyBoard);
        computer.useDevice(mouse);
        computer.powerOff();
    }
}
开机
打开键盘
打字
关闭键盘
打开鼠标
点击鼠标
关闭鼠标
关机

4. 接口特性

1.使用关键字interface来定义接口

2.接口不能被实例化

3.接口当中的成员,默认是public static final修饰,是静态常量

4.接口当中的方法,默认为public abstractd的 

5.接口当中的方法,不能有具体的实现,但是从JDK8开始,可以写 通过default修饰的方法

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

7.创建接口时,接口名一般为"I"开头,一般使用形容词

8.接口中的方法和属性尽量不加修饰符,保持简洁性.

9.接口需要被类实现,使用关键字implements

10.接口当中,可以有static修饰的方法

11.重写接口中方法时,不能使用默认的访问权限(重写子类的访问权限>=父类的)+public

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

5. 实现多个接口

public interface IRunning {
    void run();
}
public interface IFlying {
    void fly();
}

public interface ISwimming {
    void swim();
}

public abstract class Animal {
   protected String name;

    public Animal(String name) {
        this.name = name;
    }
}
public class Bird extends Animal implements IFlying{
    public Bird(String name) {
        super(name);
    }

    @Override
    public void fly() {
        System.out.println(name+"在飞");
    }
}
public class Dog extends Animal implements IRunning{
    public Dog(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(name+"在跑");
    }
}
public class Fish extends Animal implements ISwimming{

    public Fish(String name) {
        super(name);
    }

    @Override
    public void swim() {
        System.out.println(name+"在游泳");
    }
}
ublic class Duck extends Animal implements IFlying,ISwimming,IRunning{//实现多个接口
    public Duck(String name) {
        super(name);

    }

    @Override
    public void fly() {
        System.out.println(name+"在飞");
    }

    @Override
    public void run() {
        System.out.println(name+"在跑");
    }

    @Override
    public void swim() {
        System.out.println(name+"在游泳");
    }
}
public class Robot implements IRunning{
    @Override
    public void run() {
        System.out.println("机器人在跑");
    }
}
public class Test {
    public static void walk(IRunning iRunning){
         iRunning.run();
    }
    public static void fly(IFlying flyer){//只要实现了Iflying接口的,都可以接收
        flyer.fly();
    }
    public static void main(String[] args) {
        Dog dog = new Dog("大黄");
        dog.run();
        walk(dog);
        fly(new Bird("麻雀"));
        walk(new Robot());//机器人不是动物的子类,因为实现了run的接口,所以也可以接收//撇开了类型
    }
}
Java中不支持多继承,但是一个类可以实现多个接口 

6. 接口间的继承

interface A{
    void func1();
}
interface B{
    void func2();
}
interface C extends A,B{//可多继承(拓展)接口
    //具备三个接口的功能
    void func3();
}
class D implements C{
    @Override
    public void func1() {

    }

    @Override
    public void func2() {

    }

    @Override
    public void func3() {

    }
}
        类和类之间是单继承的,一个类可以实现多个接口,接口与接口之间可以多继承
用接口可以达到多继承(扩展)的目的。 接口间的继承相当于把多个接口合并在一起
接口可以继承一个接口 , 达到复用的效果 . 使用 extends 关键字

7. 接口的使用实例

7.1 给对象数组排序
Student 类实现 Comparable 接口 , 并实现其中的 compareTo 方法
 
sort 方法中会自动调用 compareTo 方法 . compareTo 的参数是 Object , 其实传入的就是 Student 类型的对象 . 然后比较当前对象和参数对象的大小关系( 按分数来算 ).
如果当前对象应排在参数对象之前 , 返回小于 0 的数字 ;
如果当前对象应排在参数对象之后 , 返回大于 0 的数字 ;
如果当前对象和参数对象不分先后 , 返回 0;
public class Student implements Comparable<Student> {
    public String name;      
    public int age;
    public int score;

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

    }

    @Override
    public int compareTo(Student o) {
//        if (this.age > o.age) {//按年龄比较
//            return 1;
//        } else if (this.age < o.age) {
//            return -1;
//        } else {
//            return 0;
//        }
        if (this.name.compareTo(o.name)>0) {//年龄比较
            return 1;
        } else if (this.name.compareTo(o.name)<0) {
            return -1;
        } else {
            return 0;
        }
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
public class Test{
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0]=new Student("z小明",18,99);
        students[1]=new Student("a小红",20,55);
        students[2]=new Student("c小华",10,77);
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));
     //   System.out.println(students[0].compareTo(students[1]));
    }
对于 sort 方法来说 , 需要传入的数组的每个对象都是 " 可比较 " , 需要具备 通过重写 compareTo 方法的方式 , 就可以比较

自己实现 sort 方法来完成排序(使用冒泡排序)  

    public static void sort(Comparable[] arr) {//口数组来接受
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j].compareTo(arr[j + 1]) > 0) {
                    Comparable temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

但是这样子写对类的侵入性很强,不灵活,不便于修改需求,所以改用比较器

public class ScoreComparator implements Comparator<Student> {//分数比较器
    @Override
    public int compare(Student o1, Student o2) {
        return o1.score-o2.score;
    }
}
public class AgeComparator implements Comparator<Student> {//年龄比较器
    @Override
    public int compare(Student o1, Student o2) {//重写compare
        return o1.age- o2.age;
        //return o2.age- o1.age;
    }
}
public static void main(String[] args) {
    Student[] students = new Student[3];
    students[0] = new Student("z小明", 18, 99);
    students[1] = new Student("a小红", 20, 55);
    students[2] = new Student("c小华", 10, 77);
    AgeComparator ageComparator = new AgeComparator();//比较器

    Arrays.sort(students,ageComparator);
    System.out.println(Arrays.toString(students));
    System.out.println("--------------------------");
    ScoreComparator scoreComparator = new ScoreComparator();//分数比较器
    Arrays.sort(students,scoreComparator);
    System.out.println(Arrays.toString(students));
}
[Student{name='c小华', age=10, score=77}, Student{name='z小明', age=18, score=99}, Student{name='a小红', age=20, score=55}]
--------------------------
[Student{name='a小红', age=20, score=55}, Student{name='c小华', age=10, score=77}, Student{name='z小明', age=18, score=99}]

 这样重新写一个类来实现Comparator接口,不在Student类中修改

8. Clonable 接口和深拷贝 

        Object 类中存在一个 clone 方法 , 调用这个方法可以创建一个对象的 " 拷贝 ". 但是要想合法调用 clone 方法 , 必须要先实现 Clonable 接口 ,
        否则就会抛出 CloneNotSupportedException 异常
        Cloneable空接口,叫标记接口:表示当前对象是可以被克隆的

 调用clone方法前,要先重写

 @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
public class Test {
    public static void main(String[] args)throws CloneNotSupportedException {
        Student student1 = new Student();
        student1.name="aaa";
        Student student2 = (Student) student1.clone();//后面的类型是父类,向下转型
        System.out.println(student1);
        System.out.println(student2);

    }
}
Student{name='aaa'}
Student{name='aaa'}
 1.浅拷贝
 public static void main(String[] args)throws CloneNotSupportedException {
        Student student1 = new Student("丁真",140);
        Student student2 = (Student) student1.clone();//后面的类型是父类,向下转型
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
        student2.m.money = 10;
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
100.12
100.12
10.0
10.0

        拷贝了学生对象,此时,两个学生对象的地址值不同,但是其中存储的money的地址值并没有改变,同时指向了一个地址,因此都发生了改变

 2.深拷贝

        此时Money也必须支持克隆,在Money类中实现Cloneable接口,重写父类的克隆方法

同时在重写克隆方法的时候,克隆Money和Student

public class Money implements Cloneable {
    public double money=100.12;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Student implements Cloneable{
    public String name;
    public Money m = new Money();
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        //return super.clone();
        Student student = (Student) super.clone();//向下转型
        student.m = (Money) this.m.clone(); //克隆Money
        return student;
    }
}
    public static void main(String[] args)throws CloneNotSupportedException {
        Student student1 = new Student();
        Student student2 = (Student) student1.clone();//后面的类型是父类,向下转型
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
        System.out.println("==============");
        student2.m.money = 10;
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
    }
}
100.12
100.12
==============
100.12
10.0

 

9. 抽象类和接口的区别

核心区别:
抽象类中可以包含普通方法和普通字段 , 这样的普通方法和字段可以被子类直接使用 ( 不必重写 ), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法

1.抽象类:普通类+抽象方法,接口:抽象方法+全局常量

2.抽象类有各种权限,接口是Public访问权限

3.一个抽象类可以实现多个接口

4.接口不能继承抽象类,但是接口能使用extends继承多个父接口

5.一个子类只能继承一个抽象类,但是一个子类可以实现多个接口

二. Object

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

1.获取对象信息

如果要打印对象中的内容,可以直接重写 Object 类中的 toString() 方法
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

        将父类的toString方法进行重写,在打印时,println内部的valueOf方法的形参是Object,同时返回tostring方法,此时,传进去一个对象,和object类型构成向上转型,同时重写了toString方法,发生了动态绑定,因此会调用我们自己写的toString方法,实现多态.

2. 对象比较equals方法

1. 如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同
2.如果 == 左右两侧是引用类型变量,比较的是引用变量地址是否相同
3.如果要比较对象中内容,必须重写 Object 中的 equals 方法,因为 equals 方法默认也是按照地址比较的

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

3. hashcode方法  

像重写 equals 方法一样,我们也可以重写 hashcode() 方法
1.hashcode方法用来确定对象在内存中存储的位置是否相同
2.事实上hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。

后记

看到这里,希望能帮到你~

您的点赞 ,收藏 ,关注 是我创作的最大动力!

同时也欢迎在评论区进行交流,共同进步~     

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值