千家信息网

Java抽象类和接口怎么用

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章将为大家详细讲解有关Java抽象类和接口怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。抽象类什么是抽象类呢?在现实生活中,我们说"人类",我们无法对应
千家信息网最后更新 2026年11月02日Java抽象类和接口怎么用

这篇文章将为大家详细讲解有关Java抽象类和接口怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

    抽象类

    什么是抽象类呢?在现实生活中,我们说"人类",我们无法对应到具体某个人,同样的,"动物类"、"图形类"这些无法映射到具体的对象的类就是抽象类。

    抽象类是普通类的超集,意思就是普通类有的抽象类也有,只是它比普通类多了一些抽象方法而已。这些抽象方法可以有一个,也可以有多个。

    它存在的意义就是让子类来覆写它的抽象方法,抽象类和抽象方法的实现使用 abstract 关键字实现:

    此时Sharp类就是抽象类,可以看到它的图标和普通类都有所不同。

    抽象方法

    示例:

    public abstract void print();

    抽象方法所在的类一定是抽象类,抽象方法只有方法声明,没有方法体{}

    注意区分没有方法体和方法体为空的情况

    public abstract void print();//这是没有方法体

    public abstract void print(){ } //这是方法体为空,它是普通方法

    抽象类三大原则

    1.抽象类无法直接实例化对象。例如上面的 Sharp 类,Sharp sharp = new Sharp();//这是错误的

    2.子类继承抽象类,必须覆写抽象类中的所有抽象方法(前提是子类是普通类)

    Triangle是一个普通类,此时没覆写方法就报错了,这时我们使用alt + enter 快捷键,点击第一行,再点击ok,就覆写了父类的抽象方法

    但是当子类依然是抽象类时,可以选择不覆写抽象方法

    3.final 和 abstract 不能同时使用、private 和 abstract 不能同时使用

    抽象类存在的最大意义就是被继承,而且它仍然满足继承关系的 is a 原则

    abstract class Person

    class Chinese extends Person √

    class Dog extends Person × //因为Dog not is a Person

    同时抽象类任然受到单继承的局限,此时我们就引出了接口来打破这两个局限

    接口

    Java使用 interface 关键字定义接口,接口中只有全局常量和抽象方法(JDK之前)JDK8扩展了default方法。子类使用 implements 实现接口

    一般接口的命名使用大写 ' I ' 字母开头,子类命名以 Impl 结尾

    全局常量:

    public static final int NUM = 10;

    抽象方法:

    public abstract String msg( );

    接口使用原则

    1.接口中只有 public 权限,且只有全局常量和抽象方法,所以 abstract、static、final、public这些关键字在接口内部都可以省略

    public interface IMassage {    int NUM = 10;//全局常量     String msg();//抽象方法}

    2.接口没有单继承限制,子类可以同时实现多个父接口,多个接口之间使用逗号分隔。此时子类必须实现父类接口中所有的抽象方法

    public interface IMassage {    int NUM = 10;//全局常量    String msg();//抽象方法} interface INews{    void getNews();} //子类public class MessageImpl implements IMassage,INews{     public String msg() {        return null;    }    public void getNews() {     }}

    接口可以使用 extends 继承多个父接口,下面的示例若类要实现接口 C ,就必须覆写 A、B、C中所有的抽象方法

        interface A{        void testA();    }    interface B{        void testB();    }    interface C extends A,B{            }

    3.接口依然不能直接实例化对象,需要通过向上转型实现

    public class MessageImpl implements IMassage,INews{     public String msg() {        return "hello JAVA";    }     public void getNews() {      System.out.println("hello n~");     }     public static void main(String[] args) {        IMassage m = new MessageImpl();        System.out.println(m.msg());     }}

    //输出:hello JAVA

    m只能调用msg方法,不能调用INews接口类定义的方法,需要用父类间的相互转换实现调用

            INews n = (INews)m;        n.getNews();

    //输出:hello n~

    4.子类若既要继承类又要实现接口,就先继承,后实现接口

    public class D extends A implements X,Y{ }

    JDK两大内置接口

    java.lang.Comparable 比较接口

    引入示例:使用排序方法比较Student类中的对象

    public class Student {    private String name;    private int age;    public Student(String name,int age){        this.name = name;        this.age = age;    }    public String toString(){        return "Student{" +    "name=" + name+'\''+ ",age="+ age + '}';    }     public static void main(String[] args) {        Student s1 = new Student("张三",18);        Student s2 = new Student("李四",20);        Student s3 = new Student("王五",30);        Student[] students = {s3,s1,s2};        Arrays.sort(students);        System.out.println(Arrays.toString(students));    }}

    运行结果:

    程序报错,因为Student类是自定义类型,当使用Arrays.sort方法对自定义类型进行排序时,自定义类型需要实现 Comparable 才具有可比较的能力

    因此我们将上述示例做如下改动:

    public class Student implements Comparable{    private String name;    private int age;    public Student(String name,int age){        this.name = name;        this.age = age;    }    public String toString(){        return "Student{" +    "name=" + name+'\''+ ",age="+ age + '}';    }    @Override    public int compareTo(Student o) {        if (this.age == o.age){            return 0;        }else if (this.age < o.age){            return -1;        }        return 1;    }     public static void main(String[] args) {        Student s1 = new Student("张三",18);        Student s2 = new Student("李四",20);        Student s3 = new Student("王五",30);        Student[] students = {s3,s1,s2};//乱序放入数组        Arrays.sort(students);        System.out.println(Arrays.toString(students));    } }

    //输出结果:
    [Student{name=张三',age=18}, Student{name=李四',age=20}, Student{name=王五',age=30}]

    可以看到数组按照年龄的升序排序,达到了预期效果。如果想要按照年龄降序排列,只需要修改 compareTo 方法中的一和负一

    实现Comparable接口,必须覆写它的compareTo方法,该方法返回的数字:

    • =0 表示当前对象等于目标对象 o

    • >0 表示当前对象等于目标对象 o

    • <0 表示当前对象等于目标对象 o

    java.lang.Cloneable 克隆接口

    在程序中,克隆是指复制一个新的对象,而这个新对象的属性值是从旧对象中拷贝过来的

    Cloneable 接口是一个标记接口,本身没有任何抽象方法,当一个类实现了 Cloneable 接口,就表示该类具备了克隆的能力,这个能力是JVM赋予的,要知道在堆上开辟空间和对象创建都由JVM实现。

    我们需要覆写 Object 类的 clone 方法,点击向上转型的图标我们就能看到 Object 提供的该方法

    可以看到,clone 方法没有方法体,用 native 关键字修饰,叫做本地方法,clone方法不是Java语言实现的,而是C++实现的,要知道JVM就是由C++实现的。所以本地方法就表示Java调用了C++的同名方法,此处只是方法声明,具体的方法实现是在C++中。所以虽然它没有方法体,但它并不是抽象方法。

    这里我们就能知道一个小知识点:没有方法体的方法不一定就是抽象方法

    代码示例:

    public class Cat implements Cloneable{    private String name;     @Override    protected Cat clone() throws CloneNotSupportedException {        return (Cat) super.clone();    }     public static void main(String[] args) throws CloneNotSupportedException {        Cat c1 = new Cat();        c1.name = "喵喵";        Cat c2 = c1.clone();        System.out.println(c1 == c2);        System.out.println(c2.name);    }}

    输出结果:

    可以看到,输出 false表示c1和c2不是同一个地址,也就是说在堆上为c2开辟了一个新空间,将c1的值拷贝给了c2

    对象的深浅拷贝

    我们先看一个示例:

    class A{    int num;}public class B implements Cloneable{    A a = new A();     @Override    protected B clone() throws CloneNotSupportedException {        return (B)super.clone();    }     public static void main(String[] args) throws CloneNotSupportedException {        B b1 = new B();        B b2 = b1.clone();        System.out.println(b1 == b2);        System.out.println(b2.a.num);        b1.a.num = 100;        System.out.println(b2.a.num);    }}

    输出:false
    0
    100

    根据结果我们看到,将b1.a的值改为100后,b2.a也随之变化,就是说b1.a 和 b2.a 指向了相同的对象

    这就是浅拷贝,拷贝出的 b1 对象只是拷贝了 b1 自身, 而没有拷贝内部包含的 a 对象. 此时 b1 和 b2 中包含的 a 引用仍然是指向同一个对象. 此时修改一边, 另一边也会发生改变.

    我们将代码做如下修改:

    class A implements Cloneable{    int num;     @Override    protected A clone() throws CloneNotSupportedException {        return (A)super.clone();    }}public class B implements Cloneable{    A a = new A();     @Override    protected B clone() throws CloneNotSupportedException {        B b = new B();        b.a = a.clone();        return b;    }     public static void main(String[] args) throws CloneNotSupportedException {        B b1 = new B();        B b2 = b1.clone();        System.out.println(b1 == b2);        System.out.println(b2.a.num);        b1.a.num = 100;        System.out.println(b2.a.num);    }}

    结果:false
    0
    0

    我们让A类也实现克隆接口,可以看到b1.a的修改没有影响b2.a,说明此时b1和b2内部包含的a对象也是不同的,这种拷贝就叫做深拷贝

    在Java中,实现深拷贝的方式有两种:一种是递归实现Cloneable,上述的例子就是递归实现的;另外一种就是通过序列化(Serializable 接口)来进行拷贝。这两种方法现在已经不常用了,现在实现深拷贝是将对象转为json字符串

    抽象类和接口的区别

    关于"Java抽象类和接口怎么用"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

    方法 接口 对象 拷贝 子类 就是 普通 示例 输出 全局 常量 结果 关键 关键字 只有 同时 多个 C++ 原则 只是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广州大一互联网络科技有限公司 互联网科技卖菜 没上市的科技互联网公司 百单互联网科技有限公司 深圳天众互联网科技公司 上游互联网科技 互联网科技网站 成都仁贤领冠互联网科技有限公司 湖南洣水互联网科技有限公司扣款 互联网科技热点资讯 小米互联网科技园设置 重庆互联网医院沙龙医盟信息科技 互联网金融科技展 西安小鹰速贷互联网科技有限公司 山东有哪些互联网科技公司 锡山区互联网智能科技产品供应 互联网金融科技公司的优势 信承诺互联网科技有限公司 互联网金融运营模式中的金融科技 互联网 科技节活动 微视频大赛 互联网高科技 互联网最新的科技有限公司 互联网 的科技创新 无锡溥仪互联网科技有限公司 蓝色互联网科技 宝灵互联网科技有限公司 高科技互联网套路 深圳互联网科技的发展 上海互联网科技园景观 知域互联网科技有限公司官网
    0