当前位置: 首页 > news >正文

Java 接口

文章目录

  • 抽象方法和抽象类
  • 接口
    • 使用接口模拟多继承
    • 接口之间的继承
    • 接口的使用实例
  • Clonable接口和深浅拷贝
  • object类
    • 对象的equals比较方法

在这里插入图片描述

抽象方法和抽象类

  1. 如果一个类中有抽象方法,那么这个类也必须是抽象类,抽象类中不一定包含抽象方法,
  2. 抽象类和抽象方法都由abstract修饰
abstract class Shape{public abstract void draw();
} 
  1. 什么叫做抽象类?
    抽象类:如果一个类不能具体地描绘一个对象,比如Animal

  2. 抽象类不能实例化对象,因为不能具体描绘一个对象

  3. 抽象类和普通类一样,可以定义成员变量和成员方法
    6. 当一个普通类继承了抽象类,必须对抽象类中的所有抽象方法进行重写,不然会报错

  4. 为什么会出现抽象类?
    为了被继承,不然没有用

  5. 抽象类不能被private修饰,不能被static和final修饰,被static和final,private修饰的不能重写,而抽象类可以重写

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

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

// 否则,到最后如果第一个抽象类中有抽象方法,
// 到最后一个类继承的时候也必须重写它的方法
abstract class Shape{}abstract class Pa extends Shape{}

抽象类的作用:提示语法错误,子类必须重写父类的抽象方法

接口

  1. 接口属于一种标准
  2. 接口是多个类的公共规范,是一种引用数据类型
  3. 语法:
    a. 接口是interface修饰的

b. 接口中的抽象方法默认都是public abstract修饰的

c. 接口中的成员变量默认都是public static final 修饰的,所以要赋个值,是常量

d. 接口中不能有被实现的方法,只能有抽象方法,除了两个方法:一个是static修饰的方法,一个是default修饰的方法

e. 接口不能实例化

f. 用类实现这个接口,使用implements关联类和接口关联,第一种使用抽象类实现这个接口,后续继承的类还要实现接口中的抽象方法,第二种实现接口中的抽象方法

g. 接口也有对应的字节码文件

public interface Shape{public abstract void draw();// == void draw();public static final int A = 1;// == int A = 1;public static void draw1(){}default public void draw2(){} 
}// Ract 类名
abstract class Ract implements Shape{}/class Ract implements Shape{public void draw(){System.out.println("矩形");}
}interface Shape{public static void draw1(){System.out.println("a");}public abstract void draw();//default public void a(){//}// public abstract void b();
}class Ract implements Shape{public void draw(){System.out.println('*');}
}class Flower implements Shape{public void draw(){System.out.println('!');}
}public class test {public static void drawMap(Shape shape){shape.draw();}public static void main(String[] args) {Shape shape1 = new Ract();Shape shape2 = new Flower();drawMap(shape1);drawMap(shape2);Shape[] shape3 = {new Ract(),new Flower(),new Ract(),new Flower()};for(Shape shape : shape3){shape.draw();}}
}

在这里插入图片描述

在这里插入图片描述

  1. 子类的访问权限必须比接口中的大,只能是public
    在这里插入图片描述
  2. 接口中不能有静态和动态代码块和构造方法
  3. 接口虽然不是类,但是编译完成后的字节码文件的后缀是.class
  4. 如果类没有实现接口中所有的抽象方法,则类必须设置为抽象类,反正到某个类继承,最后都要实现

在这里插入图片描述
5. 可以在一个包下,写一个接口,很多个类实现这个接口,最后使用这些类实例化对象,调用实现的方法,达到多态的效果

在这里插入图片描述

使用接口模拟多继承

  1. Java中没有多继承,只能想办法实现多继承
  2. 一个类可以实现多个接口
  3. 一个类继承父类具备某种特性
  4. 可以忘记类型,即使不是动物也可以使用这些接口
    在这里插入图片描述
public abstract class Animal {public String name;public int age;public Animal(String name, int age) {this.name = name;this.age = age;}public abstract void eat();
}
public interface IRunning {void run();
}
public interface ISwimming {void swim();
}
public interface IFlying {void fly();
}
public class Dog extends Animal implements IRunning,ISwimming{public Dog(String name, int age) {super(name, age);}@Overridepublic void eat() {System.out.println(name+"吃狗粮!");}@Overridepublic void run() {System.out.println(name+"用狗腿在跑");}@Overridepublic void swim() {System.out.println(name+"用狗腿游泳");}
}
public class Bird extends Animal implements IRunning,IFlying{public Bird(String name, int age) {super(name, age);}@Overridepublic void eat() {System.out.println(name+"吃鸟粮");}@Overridepublic void fly() {System.out.println(name+"用翅膀飞");}@Overridepublic void run() {System.out.println(name+"用鸟腿跑");}
}
public class Test {public static void test1(Animal animal) {animal.eat();}public static void test2(IRunning iRunning) {iRunning.run();}public static void test3(ISwimming iSwimming) {iSwimming.swim();}public static void test4(IFlying iFlying) {iFlying.fly();}public static void main(String[] args) {// 子类可以给接口,然后接口对象调用它的方法test1(new Dog("狗",4));test2(new Dog("狗",4));test3(new Dog("狗",4));System.out.println("=====================");test1(new Bird("鸟",2));test2(new Bird("鸟",2));test4(new Bird("鸟",2));}
}

接口之间的继承

  1. 接口A可以拓展接口B的功能,也就是A接口同时具备了B接口的功能

在这里插入图片描述

  1. 接口A和B都是testA的功能,那么重写的是谁的功能?
    重写的是接口B的testA()
    在这里插入图片描述

接口的使用实例

  1. 实例化两个Student对象,并比较他们的大小,无法用对象直接比较大小,可以使用实现接口比较大小

在这里插入图片描述

class Student implements Comparable<Student>{public String name;public int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}// 接口的实现@Overridepublic int compareTo(Student o) {/*法一:if(this.age > o.age) {return 1;}else if(this.age < o.age) {return -1;}else {return 0;}*///法二:return this.age - o.age;}
}// 调用这个方法比较大小
public class test{public static void main(String[] args){Student student1 = new Student("zhangsan",10);Student student2 = new Student("lisi",20);System.out.println(student1.compareTo(student2));}
}
  1. 如果这个类要根据姓名比较,是不是要修改方法,这里我们使用比较器进行比较
    age的类比较age,name的类比较name
    在这里插入图片描述
    在这里插入图片描述

  2. 对比:单独写两个对象传入的比写在类里面的比较方式灵活性更强

  3. 一般一个自定类型的类里面会写一个默认的比较方法

在这里插入图片描述
5. 可以自己写一个排序方法,使用自己类内部的比较方法进行比较

在这里插入图片描述

Clonable接口和深浅拷贝

  1. object类中有一个clone方法,调用这个方法可以创建一个对象的拷贝
  2. 我们自己写的类要实现克隆,必须实现Clonable接口

在这里插入图片描述
为什么调用不了clone方法?
1.clone方法由protected修饰,需要用super.
2.需要在子类中重写clone方法

package test1;// 有implements Cloneable接口后表明这个类是可以被克隆的class Person implements Cloneable{public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class test11 {public static void main(String[] args) throws CloneNotSupportedException{Person person = new Person("张三",20);Person person2 = (Person)person.clone();// cloneSystem.out.println(person2);System.out.println(person);}
}
  1. 浅拷贝
    克隆前:19.99 19.99
    克隆后:99.99 99.99
    为什么呢?
    因为是浅拷贝,Money对象都指向了同一份
    浅拷贝就是值拷贝,就是把person复制了一份过去

在这里插入图片描述

在这里插入图片描述

class Money{public double m = 19.99;
}class Person implements Cloneable{public int age;public String name;public Money money = new Money();public Person(int age,String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Person{" +"age=" + age +String + '}';}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}//克隆方法在Object当中,并且由protected修饰,所写类默认继承Object类
//protected:不同包中的子类.同时使用时,需要super调用
public class Test2 {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person(3);Person person2 = (Person)person1.clone();System.out.println(person1.money.m);//19.99System.out.println(person2.money.m);//19.99System.out.println("=========================");person2.m.money = 99.99;System.out.println(person1.money.m);//99.99System.out.println(person2.money.m);//99.99
//person2.m.money = 99.0;这句代码原本应该是只改变person1.m.money的值,但是person2也改变了}
}
  1. 深拷贝
    每个person都有自己的一份Money对象
    tmp出了作用域就销毁

在这里插入图片描述

class Money implements Cloneable{public double money = 19.99;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}class Person implements Cloneable{public int age;public String name;public Money money = new Money();public Person(int age,String name) {this.age = age;this.name = name;}@Overridepublic String toString() {return "Person{" +"age=" + age +String + '}';}@Overrideprotected Object clone() throws CloneNotSupportedException {//这里面在克隆person  但是我没看到你克隆money,那么怎么克隆呢?(重点)Person tmp = (Person)super.clone();tmp.money = (Money)this.money.clone();return tmp;// return super.clone();//克隆的返回值类型为Object需要强转}
}//克隆方法在Object当中,并且由protected修饰,所写类默认继承Object类
//protected:不同包中的子类.同时使用时,需要super调用
public class Test2 {public static void main(String[] args) throws CloneNotSupportedException {Person person1 = new Person(3);Person person2 = (Person)person1.clone();System.out.println(person1.money.m);// 19.99System.out.println(person2.money.m);// 19.99System.out.println("=========================");person2.m.money = 99.99;System.out.println(person1.money.m);// 19.99System.out.println(person2.money.m);// 99.99}
}

object类

  1. Java中默认所有的类都继承于object类
  2. 所有类的对象可以用object类的引用进行接收
  3. 可以重写equals方法,toString方法和hashCode方法

对象的equals比较方法

  1. 编译器默认比较的是两个对象的地址,这是不符合我们的比较的

在这里插入图片描述
2. 正确的比较方法:
重写equals

class Student{public String name;public int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic 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 && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}// 自己重写一个equals方法/*@Overridepublic boolean equals(Object obj) {Student tmp = (Student)obj;// 要同一中类型的才能比较,应该都为子类对象// return this.name.equals(obj.name);return this.name.equals(tmp.name) &&this.age == tmp.age;}*/
}
public class test11 {public static void main(String[] args) {Student person = new Student("张三",20);Student person1 = new Student("张三",20);System.out.println(person.equals(person1));}
}
  1. hashcode方法是用来算一个具体对象的位置的

在这里插入图片描述

相关文章:

  • 06-Web后端基础(java操作数据库)
  • Linux基础IO---缓冲区----文件系统----软硬链接
  • Python打卡训练营学习记录Day36
  • Spring AI 与 Python:AI 开发的新老势力对决与协作
  • git提交通用规范
  • 阿里云国际版香港轻量云服务器:CN2 GIA加持,征服海外网络的“速度与激情”!
  • 掌握聚合函数:COUNT,MAX,MIN,SUM,AVG,GROUP BY和HAVING子句的用法,Where和HAVING的区别
  • 成功解决ImportError: cannot import name ‘DTensor‘ from ‘torch.distributed.tensor‘
  • 题目 3327: 蓝桥杯2025年第十六届省赛真题-倒水
  • loss的范围
  • 读《Go语言圣经》记录(一)
  • uni-app学习笔记十三-vue3中slot插槽的使用
  • QML与C++交互2
  • 【电子通识】连接器的绝缘胶座和接触端子基础知识
  • 数据结构 栈的详细解析
  • Java——优先级队列(堆)
  • 明阳智慧能源社招校招入职测评 |iLogic言语逻辑数字、Talent5大五职业性格测评、TAS倍智人才测评考什么
  • JVM规范之栈帧
  • 我的第1个爬虫程序——豆瓣Top250爬虫的详细步骤指南
  • uni-app学习笔记十二-vue3中组件传值(对象传值)
  • html 模板网站/网络营销课程个人总结3000字
  • 网站建设 网址导航/怎么做个网站
  • 晋江免费网站建设/seo入门书籍
  • 网站数据建设涉及哪些内容/烘焙甜点培训学校
  • asp网站开发好怎么预览/app推广代理平台
  • 论述农产品电商网站建设/软文营销软文推广