Java-接口

接口

接口

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

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

  • 使用关键字interface实现接口.

  • 接口是不能被实例化的.

  • 接口中的成员变量默认是 public static final

  • 接口中只能有抽象方法,当中的方法不写,也是public abstract的,不能实现这个方法.

    • 如果非要实现,从JDK8之后,那么这个方法只能是default修饰的方法.
  • 接口中的成员变量是必须初始化的,也就说明接口中没有构造函数,不能有构造方法代码块的

  • 接口用类实现,需要使用implements调用.然后重写接口 中的方法即可.

  • 重写的时候,子类的访问修饰权限一定要>=父类的,重写函数时要注意权限书写.

  • interface IUsb{void openDevice();//默认是public abstractvoid closeDevice();
    }
    abstract class  Mouse implements IUsb {
    //如果不想重写接口中函数,需要将这个类声明为抽象类
    }
    
interface IShape{public abstract void draw();public String name="";public static int age=10;public static final int size=20;void func1();public abstract void func3();//默认成员函数default void func2(){//不写default,errorSystem.out.println("interface IShape func2()");}//静态成员函数public static void staticFunc(){System.out.println();}//    IShape(){} error}
class Rect implements IShape{//接口,必须将其中的所有方法都重写public void draw(){System.out.println("矩形: draw()");}@Overridepublic void func1() {System.out.println("矩形: func1");}@Overridepublic void func3() {System.out.println("矩形: func3");IShape.super.func2(); //调用时,需要引上IShape才能使用super}@Overridepublic void func2() {//对默认成员函数也可以完成重写System.out.println("矩形:func2");}
}
public class interfaceCode {public static void func(IShape ishape){//向上转型ishape.draw();//实现多态}public static void main(String[] args) {IShape ishape1 = new Rect();func(ishape1);//矩形: draw()IShape.staticFunc();//矩形: draw() 通过接口名访问接口中的静态方法}public static void main1(String[] args) {//向上转型IShape ishape1 = new Rect();ishape1.draw();ishape1.func1();ishape1.func2();ishape1.func3();//矩形: draw()//矩形: func1//矩形:func2//矩形: func3}
}
例子: 电脑键盘鼠标
import javafx.scene.input.KeyCode;interface IUsb{void openDevice();void closeDevice();
}
class Mouse implements IUsb{public Mouse() {super();}@Overridepublic void openDevice() {System.out.println("打开鼠标");}@Overridepublic void closeDevice() {System.out.println("关闭鼠标");}public void click(){System.out.println("点击鼠标");}
}
class KeyBoard implements IUsb{@Overridepublic void openDevice() {System.out.println("打开键盘");}@Overridepublic void closeDevice() {System.out.println("关闭键盘");}public void click(){System.out.println("敲击键盘");}
}
class Computer{public void useDevice(IUsb iusb){//参数向上转型,动态绑定实现多态.只需要各个子类都完成了接口的重写即可iusb.openDevice();if(iusb instanceof Mouse){Mouse mouse = (Mouse) iusb;//向下转型,判定之后调用即可mouse.click();}else if(iusb instanceof KeyBoard){KeyBoard keyboard = (KeyBoard) iusb;keyboard.click();}iusb.closeDevice();}
}public class interfaceCode{public static void main(String[] args) {Computer computer = new Computer();KeyBoard keyBoard= new KeyBoard();Mouse mouse = new Mouse();computer.useDevice(mouse);System.out.println("=================");computer.useDevice(keyBoard);//打开鼠标//点击鼠标//关闭鼠标//=================//打开键盘//敲击键盘//关闭键盘}
}

一个类实现多个接口

java只支持单继承,不支持多继承.所以可以以接口的形式出现.

package demo1;abstract class Animal{public String name;public int age;public Animal(String name, int age) {this.name = name;this.age = age;}
}
interface IRunning {void run();
}
interface ISwimming{void swim();
}
interface IFly{void fly();
}class Robot implements IRunning{@Overridepublic void run() {System.out.println("机器人正在跑");}
}
//鸭子水路空三栖生物,那么就重写三个接口即可
class Duck extends Animal implements ISwimming,IFly,IRunning{//接口之间 , 隔开public Duck(String name, int age) {super(name, age);}@Overridepublic void run() {System.out.println(name+ " is running !!");}@Overridepublic void swim() {System.out.println(name +  "is swimming!!");}@Overridepublic void fly() {System.out.println(name + " is flying!!");}
}
class Bird extends Animal implements IFly{public Bird(String name, int age) {super(name, age);}@Overridepublic void fly() {System.out.println(name + " is flying!!");}
}
class Fish extends Animal implements ISwimming{Fish(String name,int age){super(name,age);}@Overridepublic void swim() {System.out.println(name +  "is swimming!!");}
}
class Dog extends Animal implements IRunning{//必须得写成先继承,再实现接口public int a;public Dog(String name, int age, int a) {super(name, age);//和this(name,age,a)冲突注意!!!this.a = a;}@Overridepublic void run() {//重写接口方法System.out.println(name+ " is running !!");}
}
//class Dog extends Animal{
//    public int a;
//
//    public Dog(String name, int age, int a) {
//        super(name, age);//和this(name,age,a)冲突注意!!!
//        this.a = a;
//    }
//    //此时想给狗添加一个run()方法,但是还不能在Animal中添加并重写,因为不是所有的动物都能跑
//    //run()属于一部分动物能力,你会想到再写一个类A,继承A,然后重写run()方法,
//    //但是java不支持多继承,所以可以将这一部分动物的共性run -> 写成接口的形式重写
//
//}
public class Test {public static void iwalk(IRunning iRunning){//只要是实现了IRunning接口的都可以接收iRunning.run();}public static void iswim(ISwimming iSwimming){//只要是实现了ISwimming接口的都可以接收iSwimming.swim();}public static void ifly(IFly iFly){//只要是实现了IFly接口的都可以接收iFly.fly();}public static void main(String[] args) {Dog dog=new Dog("xd1",10,20);Duck duck =new Duck("xd2",20);iwalk(dog);iwalk(duck);//xd1 is running !!//xd2 is running !!iwalk(new Robot());//即使不是动物类型,只要是实现了这个IRunning接口就可以接收//机器人正在跑Fish fish =new Fish("xd3",30);iswim(fish);iswim(duck);//xd3is swimming!!//xd2is swimming!!Bird bird= new Bird("xd4",40);ifly(bird);ifly(duck);//xd4 is flying!!//xd2 is flying!!}
}

接口之间的继承

其实是接口的拓展extends真实含义是这样的.

package demo1;interface A{void funcA();
}
interface B{void funcB();
}
interface CC extends A,B{//因为是继承(拓展),对象那里会要求你走父类构造函数.但是因为接口并不需要构造函数,所以不用写void funcC();
}class Y implements CC{//需要将三个接口中的函数都重写@Overridepublic void funcA() {System.out.println("Y funcA");}@Overridepublic void funcB() {System.out.println("Y funcB");}@Overridepublic void funcC() {System.out.println("Y funcC");}
}
public class test2 {}

接口使用实例

package demo1;import java.util.Arrays;//class Student
class Student implements Comparable<Student>{//重写接口,指定比较规则public String name;@Overridepublic int compareTo(Student o) {//student[0].compareTo(student[1])//参数列表前面有一个隐含的this引用
//        return this.score-o.score;   //指定根据分数进行比较
//        if(this.score<o.score){
//            return -1;
//        }
//        else if(this.score>o.score){
//            return 1;
//        }
//        else {
//            return 0;
//        }//指定根据String名字进行比较if(this.name .compareTo(o.name)<0){//Sting 也是一个类,也得调用compareto方法.String类中肯定也重写了Comparable<String>接口return -1;}else if(this.name.compareTo(o.name)>0){return 1;}else{return 0;}}public int age;public int score;public Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}
}
public class test3 {//向上转型public static void sort(Comparable[] array){//因为Student重写了接口,所以这个函数可以接收所有重写这个接口的对象//可以使用冒泡排序实现排序for (int i =0; i < array.length-1; i++) {//趟数,一趟搞定一个数for(int j=0;j< array.length-1-i;j++){//下一趟就整-i个数就行了,提升效率if(array[j].compareTo(array[j+1]) >0){Comparable tmp=array[j];array[j]=array[j+1];array[j+1]=tmp;}}}}public static void main(String[] args) {Student[] student =new Student[3];student[0]=new Student("zhangsan",20,30);student[1]=new Student("lisi",30,50);student[2]=new Student("wangwu",40,10);//1. 自己实现一个比较函数sort(student);System.out.println(Arrays.toString(student));//2. Array自带的sort,然后重写比较接口即可Arrays.sort(student);//terminal// public interface Comparable<T> {//        public int compareTo(T o);//}System.out.println(Arrays.toString(student));}
}
  • 但是Student中比较规则写死了,能不能灵活一点呢?
package demo2;import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;//class Student implements  Comparable<Student>{
//    public String name;
//    public int age;
//    public int score;
//
//    @Override
//    public int compareTo(Student o) {
        if(this.score > o.score) {
            return 1;
        }else if(this.score<o.score){
            return -1;
        }else{
            return 0;
        }
//        return this.score-o.score;
//    }
//
//    public Student(String name, int age, int score) {
//        this.name = name;
//        this.age = age;
//        this.score = score;
//    }
//
//    @Override
//    public String toString() {
//        return "Student{" +
//                "name='" + name + '\'' +
//                ", age=" + age +
//                ", score=" + score +
//                '}';
//    }
//}class 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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}
}
class ScoreComp implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {return o1.score-o2.score;}
}
//比较器类,很灵活.首先传参方面,相对于上面,参数顺序可以自定义,因为上面默认前面的是this引用.
//比较方式可以自定义,不会写死.
class NameComp implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {return o1.name.compareTo(o2.name);}
}
class AgeComp implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {return o1.age-o2.age;}
}
public class test1 {public static void sort(Comparable[] arrays){for(int i=0;i<arrays.length-1;i++){for(int j=0;j<arrays.length-1-i;j++){if(arrays[j].compareTo(arrays[j+1]) >0){Comparable tmp= arrays[j];arrays[j]=arrays[j+1];arrays[j+1]=tmp;}}}}public static void main(String[] args) {Student[] students =new Student[3];students[0]= new Student("zhangsan",20,30);students[1]= new Student("lisi",10,40);students[2]= new Student("wangwu",40,10);ScoreComp scoreComp =new ScoreComp();Arrays.sort(students,scoreComp);System.out.println(Arrays.toString(students));NameComp nameComp =new NameComp();Arrays.sort(students,nameComp);System.out.println(Arrays.toString(students));AgeComp ageComp=new AgeComp();Arrays.sort(students,ageComp);System.out.println(Arrays.toString(students));}
//    public static void main1(String[] args) {
//        Student[] students =new Student[3];
//        students[0]= new Student("zhangsan",20,30);
//        students[1]= new Student("lisi",10,40);
//        students[2]= new Student("wangwu",40,10);
//
//        sort(students);
//        System.out.println(Arrays.toString(students));
//
//        Arrays.sort(students);
//        System.out.println(Arrays.toString(students));
//    }
}

Cloneable

如果想要克隆一个对象,

  • C++中提供拷贝构造和赋值构造函数,默认是浅拷贝,自定义实现是深拷贝.
  • 那么java中,就需要在这个类重写Cloneable接口.
  1. 对自定义类型进行拷贝
package demo3;
class Student implements Cloneable{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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}//返回值是Object,是所有类的父类@Overrideprotected Object clone() throws CloneNotSupportedException {//1 return super.clone();}}
public class test {public static void main(String[] args) throws CloneNotSupportedException{//添加异常处理,针对 1Student student1 =new Student("yuanwei",22,20);Student student2 = (Student)student1.clone();//Object -> Student ,向下转型,需要强转System.out.println(student1);System.out.println(student2);}
}
浅拷贝
package demo3;class Money{public  int pay = 100;
}
class Student implements Cloneable{public String name;public int age;public int score;public Money m=new Money();//组合的形式添加另一个类,成员变量m存放的是这个的引用public Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}//返回值是Object,是所有类的父类@Overrideprotected Object clone() throws CloneNotSupportedException {//1return super.clone();}}
public class test {public static void main(String[] args) throws CloneNotSupportedException{Student student1 =new Student("yuanwei",22,20);Student student2 = (Student)student1.clone();//Object -> Student ,向下转型,需要强转System.out.println(student1.m.pay);System.out.println(student2.m.pay);System.out.println("+++++++++++++++++");student1.m.pay =20;System.out.println(student1.m.pay);System.out.println(student2.m.pay);//100//100//+++++++++++++++++//20//20//更改其中一个,两个都会修改.说明Object提供的只是浅拷贝}
}

image-20231023164932406

深拷贝
package demo3;class Money implements Cloneable{public  int pay = 100;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
class Student implements Cloneable{public String name;public int age;public int score;public Money m=new Money();//组合的形式添加另一个类,成员变量m存放的是这个的引用public Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}//返回值是Object,是所有类的父类@Overrideprotected Object clone() throws CloneNotSupportedException {//在堆上克隆了一个新的student对象,Student newStudent = (Student) super.clone();//调用Object的clone(),然后u向下转型为Student//在堆上另外克隆一个Money对象newStudent.m=(Money)this.m.clone();//this 是Student1,谁调用this就是谁return newStudent;//返回值是栈中newStudent,也就是新的对象的引用
//        return super.clone();}}public class test {public static void main(String[] args) throws CloneNotSupportedException{Student student1 =new Student("yuanwei",22,20);Student student2 = (Student)student1.clone();//Object -> Student ,向下转型,需要强转System.out.println(student1.m.pay);System.out.println(student2.m.pay);System.out.println("+++++++++++++++++");student1.m.pay =20;System.out.println(student1.m.pay);System.out.println(student2.m.pay);//自定义Student中Object的clone方法之后,提供的是深拷贝//100//100//+++++++++++++++++//20//100}
}

image-20231023164856888

抽象类和接口的区别

语法层面上的区别
  • 1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
  • 2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
  • 3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
  • 4)一个类只能继承一个抽象类,而一个类却可以实现多个接口.

相同点

(1)都不能被实例化 (2)接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能实例化。

不同点

(1)接口只有定义,不能有方法的实现,java 1.8中可以定义default方法体,而抽象类可以有定义与实现,方法可在抽象类中实现。

(2)实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。

(3)接口强调特定功能的实现,而抽象类强调所属关系。

(4)接口成员变量默认为public static final,必须赋初值,不能被修改;其所有的成员方法都是public、abstract的。抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;抽象方法被abstract修饰,不能被private、static、synchronized和native等修饰,必须以分号结尾,不带花括号。

equals

package demo3;import java.util.Objects;class StudentH  {public String name;public int age;public int score;
//    public Money2 m=new Money2();//组合的形式添加另一个类,成员变量m存放的是这个的引用public StudentH(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}//重写父类中的equals方法,自己实现的
//    public boolean equals(Object obj) {
//        if(obj==null)
//            return false;
//        if(this == obj){
//            System.out.println("指向同一个对象");
//            return true;
//        }
//        if(!(obj instanceof Student)){//如果传来的不是Student类型
//            System.out.println("比较的两个对象都不是一个类型");
//            return false;
//        }
//        StudentH newStudnet =(StudentH) obj;
//
//        if(this.name.equals(newStudnet.name)){//调用String类型重写Object的equals方法
//            return true;
//        }
//        else {
//            return false;
//        }
//    }//可以使用编译器Generate的equals@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;StudentH studentH = (StudentH) o;return age == studentH.age && score == studentH.score && Objects.equals(name, studentH.name);}//Objects是Object的一个工具类@Overridepublic int hashCode() {//native方法,底层是由伟大的C++代码写的!!!return Objects.hash(name, age, score);//算一个具体对象位置,是一个内存地址,然后调用方法将这个地址以16进制输出}
}public class test_equals {public static void main(String[] args) {StudentH student1 = new StudentH("yuanwei", 22, 20);StudentH student2 = new StudentH("yuanwei", 22, 20);System.out.println(student1.name);System.out.println(student2.name);//我们希望同名的人,放到同一个位置.System.out.println(student1.hashCode());System.out.println(student1.hashCode());//1542478095//1542478095}public static void main2(String[] args)  {StudentH student1 = new StudentH("yuanwei", 22, 20);StudentH student2 = new StudentH("yuanwei", 22, 20);System.out.println(student1.name);System.out.println(student2.name);//yuanwei//yuanwei//我们的逻辑是,只要是名字相同的两个学生,就认为是一个人,实现equals方法boolean flag= student1.equals(student2);//调用重写之后的equalsSystem.out.println(flag);//true}public static void main1(String[] args) throws CloneNotSupportedException {StudentH student1 = new StudentH("yuanwei", 22, 20);StudentH student2 = new StudentH("yuanwei", 22, 20);System.out.println(student1.name);System.out.println(student2.name);//yuanwei//yuanwei//我们的逻辑是,只要是名字相同的两个学生,就认为是一个人,实现equals方法System.out.println(student1==student2);//false 比较的是对象引用是否相同,很明显不同对象引用不同boolean flag= student1.equals(student2);//默认调用的就是Object的equals方法//    public boolean equals(Object obj) {//        return (this == obj);//比较的很明显是对象引用是否相等,//    }System.out.println(flag);//false}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/208906.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

visionOS空间计算实战开发教程Day 4 初识ImmersiveSpace

细心的读者会发现在在​​Day1​​​和​​Day2​​​的示例中我们使用的都是​​WindowGroup​​。 main struct visionOSDemoApp: App {var body: some Scene {WindowGroup {ContentView()}} } 本节我们来认识在visionOS开发中会经常用到的另一个概念​​ImmersiveSpace​​…

react中模块化样式中:global的作用

在react中如果是通过import styles from ./index.less这种方式模块化引入样式的话&#xff0c;那么编译后的less文件里的样式名都会自动添加后缀。而:global的作用就是不让类名添加后缀

2023年03月 Scratch(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 小猫的程序如图所示,积木块的颜色与球的颜色一致。点击绿旗执行程序后,下列说法正确的是?( ) A:小猫一直在左右移动,嘴里一直说着“抓到了”。 B:小猫会碰到球,然后停止。…

《QT从基础到进阶·三十八》QWidget实现炫酷log日志打印界面

QWidget实现了log日志的打印功能&#xff0c;不仅可以在界面显示&#xff0c;还可以生成打印日志。先来看下效果&#xff0c;源码放在文章末尾&#xff1a; LogPlugin插件类管理log所有功能&#xff0c;它可以获取Log界面并能打印正常信息&#xff0c;警告信息和错误信息&…

加入破局 180 天,成功立起 IP

大家好&#xff0c;我是破局合伙人木川 在成为破局合伙人之前&#xff0c;我就是那个两三年不怎么发朋友圈的人&#xff0c;成为破局合伙人之后&#xff0c;开始日更朋友圈 在成为破局合伙人之前&#xff0c;我就是那个喜欢单打独斗的人&#xff0c;成为破局合伙人之后&#xf…

Unity UI设计 软件构造实验报告

实验1: 仿真系统的UI主界面设计 1.实验目的 &#xff08;1&#xff09;熟悉Unity中UI界面的设计与编写&#xff1b; &#xff08;2&#xff09;熟悉UI界面中场景转换,UI与场景内容相互关联的方式。 &#xff08;3&#xff09;熟悉Unity中MySQL数据库的操作 2.实验内容 新建…

深入了解批处理文件:从基础到实例

1. 什么是批处理文件&#xff1f; 批处理文件是一种包含一系列命令的文本文件&#xff0c;通常用于自动化执行一系列任务。在不同操作系统中&#xff0c;批处理也有不同的名称&#xff0c;如在Windows中被称为批处理文件&#xff08;.bat&#xff09;&#xff0c;而在Linux中则…

PTA-输出三角形面积和周长

本题要求编写程序&#xff0c;根据输入的三角形的三条边a、b、c&#xff0c;计算并输出面积和周长。注意&#xff1a;在一个三角形中&#xff0c; 任意两边之和大于第三边。三角形面积计算公式&#xff1a;areas(s−a)(s−b)(s−c)​&#xff0c;其中s(abc)/2。 输入格式&…

Day38力扣打卡

打卡记录 网格中的最小路径代价&#xff08;动态规划&#xff09; 链接 class Solution:def minPathCost(self, grid: List[List[int]], moveCost: List[List[int]]) -> int:m, n len(grid), len(grid[0])f [[0x3f3f3f3f3f] * n for _ in range(m)]f[0] grid[0]for i i…

8-cgi fastcgi wsgi uwsgi uWSGI 分别是什么?如何自定制上下文管理器、Python是值传递还是引用传递

1 cgi fastcgi wsgi uwsgi uWSGI 分别是什么&#xff1f; 2 如何自定制上下文管理器 3 Python是值传递还是引用传递 1 cgi fastcgi wsgi uwsgi uWSGI 分别是什么&#xff1f; # CGI:通用网关接口&#xff08;Common Gateway Interface/CGI&#xff09;,CGI描述了服务器&#xf…

iperf3 网络测试

iperf3 测试网络的上下行带宽 下载地址 https://iperf.fr/iperf-download.php 开启服务器 开启客户端 常用命令 -c 代表客户端-s 代表服务端-u 代表 udp-r 代表数据方向是否反向 https://baijiahao.baidu.com/s?id1731514357681464971&wfrspider&forpc

智能驾驶产品开发中如何贯彻“正向开发”理念

摘要&#xff1a; 基于演绎法的正向开发理念&#xff0c;能够让智能驾驶产品在充分满足用户需求&#xff0c;保证产品质量的同时&#xff0c;确保开发目标合理且得到落实。 前段时间&#xff0c;微博CEO吐槽理想L9智能驾驶“行驶轨迹不居中”&#xff0c;在网上引发了热烈讨论…