• Java抽象类和接口


    目录

    1.抽象类

    1.1 抽象类的语法

    1.2 抽象类的特点

    2.Object类

    2.1 equals方法

    3.接口

    3.1 接口的语法

    3.2 接口的使用及特性

    3.3 Comparable接口和Comparator接口

    3.3.1 Compapable接口

    3.3.2 Comparator接口

    3.4 Cloneable接口和深拷贝


    1.抽象类

    1.1 抽象类的语法

    被abstract修饰的类称为抽象类,被abstract修饰的方法称为抽象方法

    1. abstract class Draw {
    2. public Draw() {
    3. System.out.println("Draw的构造方法");
    4. }
    5. //抽象方法不能有主体
    6. public abstract void draw();
    7. public void func() {
    8. System.out.println("Draw::func()");
    9. }
    10. }

    抽象方法不可以有主体。

    抽象类和其他类一样可以有自己的成员属性和方法,以及构造方法。

    1.2 抽象类的特点

    1.抽象类与普通类的区别就是:抽象类中可以有抽象方法(也可以没有)

    2.抽象类不能直接实例化对象

    1. public static void main(String[] args) {
    2. //Draw是抽象类
    3. Draw draw0 = new Draw(); //---Error---
    4. //会报错
    5. }

    3.抽象方法不可以被private修饰符修饰,被final、static修饰的方法也不能成为抽象方法

    1. abstract class Draw {
    2. public Draw() {
    3. System.out.println("Draw的构造方法");
    4. }
    5. //抽象方法不能有主体
    6. public abstract void draw();
    7. //private abstract void draw1(); ---Error---
    8. //public final abstract void draw2(); ---Error---
    9. //public static abstract void draw3(); ---Error---
    10. public void func() {
    11. System.out.println("Draw::func()");
    12. }
    13. }

    4.当抽象类被继承后,子类必须要重写父类(抽象类) 的抽象方法,如果子类不想重写抽象方法,那么子类必须是抽象类,但是当子类再次被继承时,子类的子类必须重写所有的抽象方法。

    比如:类A是抽象类,抽象类 类B继承了类A,类C继承了类B,那么类C中必须重写类A和类B中的所有抽象方法。

    5.抽象类也有多态性

    2.Object类

    Object类是所有类的父类,所以,所有类都可以重写或直接调用Object类中的方法

    2.1 equals方法

    equals方法是比较两个变量是否相等,范围boolean类型

    原码如下:

    1. public boolean equals(Object obj) {
    2. return (this == obj); // 使用引用中的地址直接来进行比较
    3. }

    如果要比较的是像int、char这种基本类型的数值,可以直接使用原码的equals方法

    如果要比较两个引用的地址,也可以直接使用equals方法

    但是如果比较的两个对象,那么就需要重写equals方法

    1. class Person1 {
    2. public String name;
    3. public int age;
    4. public Person1(String name, int age) {
    5. this.name = name;
    6. this.age = age;
    7. }
    8. public boolean equals(Object obj) {
    9. if (this == obj) {
    10. return true;
    11. }
    12. if (obj == null) {
    13. return false;
    14. }
    15. if (!(obj instanceof Person1)) {
    16. return false;
    17. }
    18. Person1 person = (Person1) obj;
    19. if (this.name.equals(person.name) && this.age == person.age) {
    20. return true;
    21. }
    22. return false;
    23. }
    24. }
    25. public class Test {
    26. public static void main(String[] args) {
    27. Person1 person1 = new Person1("张三", 18);
    28. Person1 person2 = new Person1("张三", 18);
    29. //System.out.println(person1.equals(person2)); // 没重写equals方法前是 false
    30. System.out.println(person1.equals(person2));//重写后是true
    31. }
    32. }

    3.接口

    3.1 接口的语法

    1.被interface修饰的是接口

    2.接口中的成员变量默认是public static final类型

    3.接口中的方法默认是public abstract类型

    1. interface USB {
    2. //普通成员会默认为public static final类型
    3. public static final int ret = 10;
    4. int ret1 = 20;
    5. public abstract void open();
    6. void close();//默认public abstract类型
    7. }

    3.2 接口的使用及特性

    1.接口与接口之间的使用时继承关系,接口可以继承另一个接口。

    2.接口与类之间的使用要用 implements 实现关系,并且一个类可以同时接收多个接口。

    3.类接收接口之后必须重写接口中的抽象方法,如果不想重写,那么类必须是抽象类。

    4.接口不可以被实例化。

    5.接口中的方法只能被 public abstract 修饰,且不能被实现,在 jdk1.8 及以后可以有 static 修饰或者被 default 修饰的方法且可以实现,除此之外,不可以被其他修饰符修饰。

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

    1. interface USB {
    2. //普通成员会默认为public static final类型
    3. public static final int ret = 10;
    4. int ret1 = 20;
    5. public abstract void open();//默认public abstract类型
    6. void close();
    7. public static void func() {
    8. System.out.println("jdk1.8及以后 接口中可以有 static 方法");
    9. }
    10. default void fun() {
    11. System.out.println("jdk1.8及以后 接口中可以有 default 修饰的方法");
    12. }
    13. }
    14. interface USB1 {
    15. }
    16. /**
    17. * 1.如果不想重写接口中的抽象类 必须被修饰成抽象类
    18. * 但是如果有其他类继承了这个类 那么仍然需要重写这些方法
    19. */
    20. abstract class A implements USB {
    21. }
    22. /**
    23. * 1.重写的方法不能用默认的访问权限 因为重写后的范围要大于等于之前的范围
    24. * 2.类和接口之间用 implements 来实现多个接口
    25. */
    26. class Mouse implements USB,USB1 {
    27. public void open() {
    28. System.out.println("打开鼠标");
    29. }
    30. public void close() {
    31. System.out.println("关闭鼠标");
    32. }
    33. public void use() {
    34. System.out.println("使用鼠标");
    35. }
    36. }

    3.3 Comparable接口和Comparator接口

    3.3.1 Compapable接口

    我们在进行自定义类型比较的时候,没办法直接通过简单的 大于、小于、等于 来判断,这时我们可以在类中添加一个Compapable接口,并重写里面的compareTo方法

    compareTo方法中自己去设置比较的条件,下面举一个例子

    1. class Student implements Comparable {
    2. public String name;
    3. public int age;
    4. public Student(String name, int age) {
    5. this.name = name;
    6. this.age = age;
    7. }
    8. @Override
    9. public String toString() {
    10. return "Student{" +
    11. "name='" + name + '\'' +
    12. ", age=" + age +
    13. '}';
    14. }
    15. @Override
    16. public int compareTo(Student o) {
    17. return this.age - o.age;
    18. }
    19. }
    20. public static void main(String[] args) {
    21. Student student1 = new Student("bit", 10);
    22. Student student2 = new Student("hello", 40);
    23. if (student1.compareTo(student2) > 0) {
    24. System.out.println("student1 > student2");
    25. } else {
    26. System.out.println("student1 <= student2");
    27. }
    28. }

    compareTo的返回是int类型,我们定义了一个Student类,里面有nameage属性,代码里面是用age的大小来做比较的条件,那么当我们想通name来做比较的条件就会变得很复杂,因为compareTo方法也叫被重写过了,这时就可以用到另一个接口Comparator

    3.3.2 Comparator接口

    当我们需要对一个自定义类型用多种方式来进行比较大小时,就可以再定义一个新的类,让新的类去继承Comparator接口,然后去实现里面的compare方法(返回值也是int),来达到用多种方式比较自定义类型大小的目的。

    实例如下:

    1. class Student implements Comparable {
    2. public String name;
    3. public int age;
    4. public Student(String name, int age) {
    5. this.name = name;
    6. this.age = age;
    7. }
    8. @Override
    9. public String toString() {
    10. return "Student{" +
    11. "name='" + name + '\'' +
    12. ", age=" + age +
    13. '}';
    14. }
    15. @Override
    16. public int compareTo(Student o) {
    17. return this.age - o.age;
    18. }
    19. }
    20. class AgeComparator implements Comparator {
    21. @Override
    22. public int compare(Student o1, Student o2) {
    23. return o1.age - o2.age;
    24. }
    25. }
    26. class NameComparator implements Comparator {
    27. @Override
    28. public int compare(Student o1, Student o2) {
    29. return o1.name.compareTo(o2.name);
    30. }
    31. }
    32. public static void main(String[] args) {
    33. Student[] students = new Student[3];
    34. students[0] = new Student("bit", 10);
    35. students[1] = new Student("hello", 40);
    36. students[2] = new Student("abc", 30);
    37. AgeComparator ageComparator = new AgeComparator();
    38. Arrays.sort(students, ageComparator);
    39. System.out.println(Arrays.toString(students));
    40. NameComparator nameComparator = new NameComparator();
    41. Arrays.sort(students, nameComparator);
    42. System.out.println(Arrays.toString(students));
    43. }

    实例中分别用了两个类去实现Student类用name比较大小和用age比较大小,最后的结果大家可以自己去试一下。

    3.4 Cloneable接口和深拷贝

    当我们想将一个对象拷贝到另一个相同类型的对象里去时,需要调用Object类里的clone方法,但是要调用这个方法需要要先实现Cloneable接口,否则就会抛出 CloneNotSupportedException 异常。

    举个例子:

    1. class Money {
    2. public double m = 12.5;
    3. }
    4. /**
    5. * 调用Object类的clone方法 必须要接收Cloneable接口
    6. * 并且要重写clone()方法
    7. * 用protected修饰的 在不同包中访问 需要用super
    8. */
    9. class Person implements Cloneable{
    10. public int id;
    11. public Money money = new Money();
    12. /**
    13. * 浅拷贝
    14. * 浅拷贝是将这个类对象拷贝过去,但是其里面的组合对象不会再拷贝一份,而是指向同一个对象
    15. */
    16. @Override
    17. protected Object clone() throws CloneNotSupportedException {
    18. return super.clone();
    19. }
    20. @Override
    21. public String toString() {
    22. return "Person{" +
    23. "id=" + id +
    24. '}';
    25. }
    26. }
    27. public class Test3 {
    28. public static void main(String[] args) throws CloneNotSupportedException{
    29. Person person1 = new Person();
    30. person1.id = 99;
    31. Person person2 = (Person)person1.clone();
    32. }
    33. }

    我们可以看到,在Person类中有一个组合对象money,当我们拷贝了person1给到person2后,money里面的数据并不会拷贝一份,而是两个Person类对象的money指向了同一块数据,当person1或者person2区修改money里面的数据时,另一个的money也会跟着修改,这是浅拷贝。

    那么如果我们想要两个Person对象里面的money不指向同一块数据,就需要进行深拷贝。

    实例如下:

    1. class Money implements Cloneable{
    2. public double m = 12.5;
    3. @Override
    4. protected Object clone() throws CloneNotSupportedException {
    5. return super.clone();
    6. }
    7. }
    8. class Person implements Cloneable{
    9. public int id;
    10. public Money money = new Money();
    11. /**
    12. * 浅拷贝
    13. * 浅拷贝是将这个类对象拷贝过去,但是其里面的组合类对象不会再拷贝一份,而是指向同一个对象
    14. */
    15. // @Override
    16. // protected Object clone() throws CloneNotSupportedException {
    17. // return super.clone();
    18. // }
    19. /**
    20. * 深拷贝
    21. * 深拷贝是指将这个对象 及其里面的组合类对象 全部拷贝一份,
    22. * 与浅拷贝不同地方在于,拷贝出来的对象里面的组合对象不会和圆对象指向同一个
    23. */
    24. @Override
    25. protected Object clone() throws CloneNotSupportedException {
    26. Person tmp = (Person)super.clone();
    27. tmp.money = (Money)this.money.clone();
    28. return tmp;
    29. }
    30. @Override
    31. public String toString() {
    32. return "Person{" +
    33. "id=" + id +
    34. '}';
    35. }
    36. }
    37. public class Test3 {
    38. public static void main(String[] args) throws CloneNotSupportedException{
    39. Person person1 = new Person();
    40. person1.id = 99;
    41. Person person2 = (Person)person1.clone();
    42. person2.money.m = 1999;
    43. System.out.println("person1: " + person1.money.m);
    44. System.out.println("person2: " + person2.money.m);
    45. }
    46. }

    我们先将person1的数据进行浅拷贝到一个的Person类对象,然后将person1的money拷贝到新对象中的money(Money类也序要实现clone接口),这时两个对象的money的指向就不同了,但是里面的数据时相同的,这就是深拷贝。

  • 相关阅读:
    查询利器—索引
    大数据预测模型的深度学习导论
    工厂模式
    聊聊如何利用管道模式来进行业务编排(下篇)
    目标跟踪ZoomTrack: Target-aware Non-uniform Resizing for Efficient Visual Tracking
    【SLAM】初识SLAM
    论文阅读:YOLOV: Making Still Image Object Detectors Great at Video Object Detection
    鲜花店经营配送小程序商城的作用是什么?
    JavaWeb开发之——DDL-操作表-数据类型(08)
    51单片机太阳能十字路口交通灯
  • 原文地址:https://blog.csdn.net/m0_64318128/article/details/126825554