首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >抽象类与接口

抽象类与接口

作者头像
景画
发布2025-12-19 13:51:25
发布2025-12-19 13:51:25
360
举报

一. 抽象类

(一)定义

  1. 当一个抽象类描述的不是一个具体的对象的时候,这个类为抽象类
  2. 抽象类与抽象方法都用abstract 修饰

(二)性质

  1. 抽象类当中可以有普通的成员变量和成员方法,且不一定要有抽象方法,没有抽象方法也可以定义抽象类
代码语言:javascript
复制
abstract class Animal {
    public String name;
    public int age;
    private void test() {
    }
}
  1. 如果一个类中有抽象方法,那么这个类必须是抽象类
代码语言:javascript
复制
abstract class Animal {
    public String name;
    public int age;
    private void test() {
        
    }
    public abstract void eat();
}
  1. 抽象方法不能被实例化,只能被继承,通过向上转型来使用,可以说抽象类意义就是用来被继承
代码语言:javascript
复制
abstract class Animal {
    public String name;
    public int age;
    private void test() {

    }
    public abstract void eat();

}
public class Test {
    public static void main(String[] args) {
       // Animal animal = new Animal();  **error**
       Animal animal = new Dog();
    }
}
  1. 抽象类可以有构造方法,子类继承抽象类时,调用构造方法来给成员变量进行初始化
代码语言:javascript
复制
abstract class Animal {
    public String name;
    public int age;
    private void test() {

    }
    public abstract void eat();

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
  1. 当子类继承抽象类时,需要重写父类的抽象方法
代码语言:javascript
复制
public class Dog extends Animal {
    @Override
    public void eat() {
        this.name = "旺财";
        this.age = 3;
        System.out.println(age + " 岁的 " + name + " 正在吃狗粮!");
    }

}
  1. 当一个抽象子类S继承了抽象父类F时,子类S可以不重写父类F的抽象方法,但是当一个普通类继承S的时候,需要重写两个S与F的两个抽象类的抽象方法
代码语言:javascript
复制
abstract class Animal {
    public String name;
    public int age;
    private void test() {

    }
    public abstract void eat();

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
abstract class Dog1 extends Animal{
    public String kinds;

    public Dog1(String name, int age) {
        super(name, age);
    }

    public abstract void setKinds();
}
class Teddy extends Dog1{

    public Teddy(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println(name + "正在吃狗粮!");
    }

    @Override
    public void setKinds() {
        kinds = "泰迪狗";
        System.out.println("种类是: " + kinds);
    }
}
public class Test {
    public static void main(String[] args) {
        Teddy teddy = new Teddy("泰迪",10);
        teddy.eat();
        teddy.setKinds();
    }
}
图片演示
图片演示
  1. 抽象类方法不能privatefinalstatic修饰
**static**修饰
**static**修饰
**private**修饰
**private**修饰
**final**修饰
**final**修饰

二. 接口

(一)定义

  1. 已知在Java中不支持类的多继承,所以要想具备多个类的功能,接口就诞生了
  2. 接口用interface修饰

(二)性质

  1. 接口中的方法默认是抽象方法,由public abstract修饰,没有具体的实现
代码语言:javascript
复制
public interface Fly {
    public abstract void fly();
    
}
  1. 接口当中的成员属性默认是静态不可变的,由public static final修饰
代码语言:javascript
复制
public interface Run {
    public static final int age = 10;
}
  1. 一个类能实现多个接口,实现接口时必须要重写接口当中所有抽象方法
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
public class chicken implements Fly,Run{
    public String name = "功夫鸡";
    @Override
    public void fly() {
        System.out.println(name + " 正在飞~");
    }

    @Override
    public void run() {
        System.out.println(name + " 正在满院跑~");
    }
}
  1. 接口当中没有构造方法
在这里插入图片描述
在这里插入图片描述
  1. 接口当中defaultstatic,修饰的方法可以有具体实现
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
public interface Swim {
    void swim();
    default void tmp1() {
        System.out.println("这是一个default修饰的方法");
    }
    public static void tmp2() {
        System.out.println("这是一个public static修饰的方法");
    }
    private static void tmp3() {
        System.out.println("这是一个private static修饰的方法");
    }
}
  1. 当一个类实现接口时,可以用接口来接受该类对象,实现动态绑定
在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
public class Fish implements Swim{
    public String name = "锦鲤";

    @Override
    public void swim() {
        System.out.println(this.name + " 正在水里游来游去~");
    }
    public void rat() {

    }

    public static void main(String[] args) {
        Swim swim = new Fish();

    }
}
  1. 因为接口中所有抽象方法都是public修饰的,所以子类重写抽象方法时,必须用public修饰
  2. 接口与接口之间可以用extends来扩展多个接口之间功能
在这里插入图片描述
在这里插入图片描述

三. 抽象类与接口的区别

抽象类

接口

用abstract修饰

用interface修饰

有构造方法

没有构造方法

有普通成员方法,可以有具体实现

默认是抽象方法,不可以有具体实现,只有static与default修饰的方法才能有具体实现

有普通成员变量

成员变量全被public static final修饰

子类用extends来继承抽象类

类用implements来实现接口的功能

抽象类与抽象类之间用extends来继承,且不能多继承

接口与接口之间用extends来拓展多个接口的功能

四. clonable,深拷贝与浅拷贝

(一)浅拷贝

1. 含义与图片演示

当克隆对象的成员变量中含有另一个类或对象的引用,通过clone1克隆clone2那么在克隆过程中,改变clone1所指的成员变量中的引用里所指的值,clone2也随之改变,称之为浅拷贝

浅拷贝
浅拷贝
在这里插入图片描述
在这里插入图片描述
2. 代码
代码语言:javascript
复制
class Name {
    public String name = "天才";
}

public class Clone implements Cloneable {
    public int age = 18;
    public Name N = new Name();
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Clone{" +
                "age=" + age + ", name=" + N.name+
                '}';
    }
}
class Test{
    public static void main(String[] args) throws CloneNotSupportedException {
        Clone clone1 = new Clone();
        Clone clone2 = (Clone) clone1.clone();
        System.out.println(clone1);
        System.out.println(clone2);
        System.out.println("---------------");
        clone1.N.name = "王八";
        System.out.println(clone1);
        System.out.println(clone2);
    }
}

(二)深拷贝

1. 含义与图片演示

当克隆对象的成员变量中含有另一个类或对象的引用,通过clone1克隆clone2那么在克隆过程中,改变clone1所指的成员变量中的引用里所指的值,clone2不会随之改变,称之为深拷贝

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2. 代码
代码语言:javascript
复制
class Name implements Cloneable{
    public String name = "天才";

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class Clone implements Cloneable {
    public int age = 18;
    public Name N = new Name();
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Clone tmp = (Clone) super.clone();
        tmp.N =(Name) this.N.clone();
        return tmp;
    }

    @Override
    public String toString() {
        return "Clone{" +
                "age=" + age + ", name=" + N.name+
                '}';
    }
}
class Test{
    public static void main(String[] args) throws CloneNotSupportedException {
        Clone clone1 = new Clone();
        Clone clone2 = (Clone) clone1.clone();
        System.out.println(clone1);
        System.out.println(clone2);
        System.out.println("---------------");
        clone1.N.name = "王八";
        System.out.println(clone1);
        System.out.println(clone2);
    }
}

五. 内部类

(一)静态内部类

1. 含义

在类中用static修饰的内部类

在这里插入图片描述
在这里插入图片描述
2. 特点

静态内部类不能直接访问外部类的非静态成员变量和方法 需要访问的话,要在静态内部类中实例化外部类对象

3. 代码
代码语言:javascript
复制
class Outer {
    public static String a;
    private int b;
    public int c;

    static class Node{
        public Node prev;
        public Node next;
        Outer outer = new Outer();
        public void fac() {
            a = "天才";
            outer.eat();
        }
    }

    public  void eat() {

    }
}

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();

    }
}

(二)实例内部类

1. 含义

在类中不加修饰词的内部类

1
1
2.特点

实例内部类中可以直接访问外部类所有的成员变量与方法

3. 代码
代码语言:javascript
复制
class Outer {
    public static String a;
    private int b;
    public int c;

    class Node{
        public Node prev;
        public Node next;
        public void fac() {
            a = "天才";
            b = 1;
            c = 2;
            eat();
        }
    }

    public void eat() {

    }
}

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Node node = outer.new Node(); // 方式一

        Outer.Node node1 = new Outer().new Node(); // 方式二
    }
}

(三)局部内部类

1. 含义

定义在方法中的内部类

2. 特点

只在该方法中能调通,生命周期伴随方法销毁而结束

3.代码
代码语言:javascript
复制
    public void fac() {
        class Node {
            public Node a;
            public Node b;
        }
    }

(四)匿名内部类

1. 含义

在实例化类的同时定义类

在这里插入图片描述
在这里插入图片描述
2. 特点

只能用一次,通常设置比较器用的多

3. 代码
代码语言:javascript
复制
class Person  {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Person person1 = new Person("ran",18);
        Person person2 = new Person("liu",20);
        Person person3 = new Person("zzz",17);

        Person[] people = new Person[3];
        people[0] = person1;
        people[1] = person2;
        people[2] = person3;
        Comparator<Person> Age_comparator = new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.age - o2.age;
            }
        };
        Comparator<Person> Name_comparator = new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.name.compareTo(o2.name);
            }
        };
        Arrays.sort(people,Name_comparator);
        System.out.println(Arrays.toString(people));
    }
}

六. comparable接口与comparator比较器

(一)comparable

1. 定义

实现comparable接口中要重写compareTo方法,又因为compareTo只有一个参数,所以是用在需要比较的类当中实现comparable接口来进行比较的

2.局限

只能比较单一属性,当需要比较多个属性的时候,comparable接口无法实现该功能

3. 代码及效果图
代码语言:javascript
复制
class Person implements Comparable<Person> {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Person person1 = new Person("ran",18);
        Person person2 = new Person("liu",20);
        Person person3 = new Person("zzz",17);

        Person[] people = new Person[3];
        people[0] = person1;
        people[1] = person2;
        people[2] = person3;

        Arrays.sort(people);
        System.out.println(Arrays.toString(people));
    }
}
在这里插入图片描述
在这里插入图片描述

(二)comparator

1. 定义

实现comparator接口要实现compare方法,该方法有两个参数,因此是定义在需要比较的类的外面的

2. 优点

可以根据类的多个属性,来设置不同的比较器,排序时,直接调用需要的比较器即可

3. 代码及效果图
1)按照姓名比较
代码语言:javascript
复制
class Person /*implements Comparable<Person>*/ {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

/*    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }*/

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Person person1 = new Person("ran",18);
        Person person2 = new Person("liu",20);
        Person person3 = new Person("zzz",17);

        Person[] people = new Person[3];
        people[0] = person1;
        people[1] = person2;
        people[2] = person3;
        Comparator<Person> Age_comparator = new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.age - o2.age;
            }
        };
        Comparator<Person> Name_comparator = new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.name.compareTo(o2.name);
            }
        };
        Arrays.sort(people,Name_comparator);
        System.out.println(Arrays.toString(people));
    }
}
在这里插入图片描述
在这里插入图片描述
2)按照年龄比较
代码语言:javascript
复制
class Person /*implements Comparable<Person>*/ {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

/*    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }*/

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        Person person1 = new Person("ran",18);
        Person person2 = new Person("liu",20);
        Person person3 = new Person("zzz",17);

        Person[] people = new Person[3];
        people[0] = person1;
        people[1] = person2;
        people[2] = person3;
        Comparator<Person> Age_comparator = new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.age - o2.age;
            }
        };
        Comparator<Person> Name_comparator = new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.name.compareTo(o2.name);
            }
        };
        Arrays.sort(people,Age_comparator);
        System.out.println(Arrays.toString(people));
    }
}

七. 总结

这篇博客按照所学知识,从抽象类到接口再到内部类,再用接口与内部类实现比较器,层序渐进慢慢展开,希望能对你有所帮助,如果大佬们发现有错误可以留言指出

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. 抽象类
    • (一)定义
    • (二)性质
  • 二. 接口
    • (一)定义
    • (二)性质
  • 三. 抽象类与接口的区别
  • 四. clonable,深拷贝与浅拷贝
    • (一)浅拷贝
      • 1. 含义与图片演示
      • 2. 代码
    • (二)深拷贝
      • 1. 含义与图片演示
      • 2. 代码
  • 五. 内部类
    • (一)静态内部类
      • 1. 含义
      • 2. 特点
      • 3. 代码
    • (二)实例内部类
      • 1. 含义
      • 2.特点
      • 3. 代码
    • (三)局部内部类
      • 1. 含义
      • 2. 特点
      • 3.代码
    • (四)匿名内部类
      • 1. 含义
      • 2. 特点
      • 3. 代码
  • 六. comparable接口与comparator比较器
    • (一)comparable
      • 1. 定义
      • 2.局限
      • 3. 代码及效果图
    • (二)comparator
      • 1. 定义
      • 2. 优点
      • 3. 代码及效果图
  • 七. 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档