Java(六)——抽象类与接口

文章目录

  • 抽象类和接口
    • 抽象类
      • 抽象类的概念
      • 抽象类的语法
      • 抽象类的特性
      • 抽象类的意义
    • 接口
      • 接口的概念
      • 接口的语法
      • 接口的特性
      • 接口的使用
      • 实现多个接口
      • 接口与多态
      • 接口间的继承
      • 抽象类和接口的区别

抽象类和接口

抽象类

抽象类的概念

Java使用类实例化对象来描述现实生活中的实体,不过,不是所有的类都能描述实体的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类(准确来说,我们可以将这样的类设计成抽象类)。

以画图形为例,有如下代码:

//Shape.java
public class Shape {public void draw() {System.out.println("画一个图形");}
}//Pentagram.java
public class Pentagram extends Shape {@Overridepublic void draw() {System.out.println("五角星☆");}
}//Rotundity.java
public class Rotundity extends Shape {@Overridepublic void draw() {System.out.println("圆形⭕");}
}

我们在实现Shape类的draw方法时,由于Shape是一个宽泛的概念,不是一个具体的图形,所以我们实际上是没办法实现的,上代码中的实现也没有实际的意义,因此,我们可以将Shape类设计成抽象类,而对于Shape类中的draw方法,我们可以将它设计成抽象方法.


抽象类的语法

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

抽象方法不用给出具体的实现。(这是强制的,不能给出方法体

将上面的Shape类设计成抽象类,draw方法设计成抽象方法:

//Shape.java
public abstract class Shape {public abstract void draw();
}

注意: 抽象类也是类,抽象类也可以有普通的成员方法、成员变量或构造方法。

抽象类与普通类的区别是抽象类有abstract修饰,且可以存在抽象方法(不存在也可以)。


抽象类的特性

  1. 抽象类不能实例化对象

    public class Test {public static void main(String[] args) {Shape shape = new Shape();//实例化抽象类,报错}
    }
    

在这里插入图片描述

抽象类虽然不能实例化,但是抽象类的引用可以引用其子类的对象

//Shape.java
public abstract class Shape {public abstract void draw();
}//Pentagram.java
public class Pentagram extends Shape {@Overridepublic void draw() {System.out.println("五角星☆");}
}//Rotundity.java
public class Rotundity extends Shape {@Overridepublic void draw() {System.out.println("圆形⭕");}
}//Test.java
public class Test {public static void func(Shape shape) {shape.draw();}public static void main(String[] args) {Pentagram pentagram = new Pentagram();Rotundity rotundity = new Rotundity();Shape[] shapes = {pentagram, rotundity};//向上转型for(Shape shape : shapes){func(shape);}}
}
  1. 抽象类必须被继承,且继承抽象类的子类必须重写抽象类中的抽象方法,如果不想重写抽象方法,需要加abstract修饰。不过,一旦这个类被一个普通的类继承,则此普通类必须重写所有的抽象方法。

    public abstract class Test {public abstract void func1();
    }abstract class A extends Test {public abstract void func2();
    }class B extends A {@Overridepublic void func1() {System.out.println("重写抽象类Test的抽象方法");}@Overridepublic void func2() {System.out.println("重写抽象类A的抽象方法");}
    } 
    

    ​ 抽象类A继承了抽象类Test,普通类B继承了A,那么普通类B必须重写A 类和Test类中的所有抽象方法。

  2. 由于抽象方法必须被重写,所以抽象方法不能被privatefinalstatic修饰

  3. 抽象类中可以不包含抽象方法,但抽象方法必须在抽象类中

    public class Test {public abstract void func();
    }
    

    在这里插入图片描述

  4. 抽象类中可以存在构造方法,用于子类实例化时初始化父类的成员

    //Shape.java
    public abstract class Shape {public int a;//抽象类的构造方法public Shape(int a) {this.a = a;}public abstract void draw();
    }//Pentagram.java
    public class Pentagram extends Shape {public Pentagram(int a) {super(a);}@Overridepublic void draw() {System.out.println("五角星☆");}
    }//Rotundity.java
    public class Rotundity extends Shape {public Rotundity(int a) {super(a);}@Overridepublic void draw() {System.out.println("圆形⭕");}
    }//Test.java
    public class Test {public static void main(String[] args) {Shape shape = new Pentagram(20);System.out.println(shape.a);}
    }
    

    打印结果是:
    在这里插入图片描述


抽象类的意义

我们可能会有一个疑问,普通类也可以被继承,普通的成员方法也可以被重写,为什么要用抽象类和抽象方法呢?

抽象类中的抽象方法如果没有被重写,编译器会报错。 是的,使用抽象类和抽象方法的好处就是多了一层编译器的校验,能帮助我们检查抽象方法是否被重写。

抽象类不能被实例化。 很多引用场景,比如上面的画图形场景,其实际工作不应该由父类完成,而应由子类完成,此时误用父类编译器会报错。

总的来说,使用抽象类就是为了预防出错,并让我们尽早发现问题,充分利用编译器的校验,在实际开发中是非常有意义的。


接口

接口的概念

接口(英文:Interface),在JAVA编程语言中是一个抽象(引用)类型,是抽象方法的集合。一个类通过继承接口的方式,从而来继承接口的抽象方法。

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

我们很容易联想到实际生活中电脑的USB接口,它是一个标准,符合这个标准,就可以与电脑交互(可以插U盘、鼠标等)。

Java中的接口也是公共行为的规范,我们在实现时,只要符合标准,就可以通用。所以,接口可以看作是:多个类的公共规范,是一种引用类型


接口的语法

接口的定义与类的定义类似,只需要把关键字class换成interface

接口只能被publicabstract修饰,abstract默认不显性显示,如果省略public则使用默认的访问权限

public interface 接口名 {//...
}
  • 接口的命名一般是以I开头
  • 接口的命名一般使用形容词词性的单词,这样就能显示出接口的标准

接口的特性

  1. 接口是一种引用类型,但是不能直接实例化对象(接口实际上比抽象类更加抽象),不过接口可以引用实现该接口的类的对象(向上转型)

        public static void main(String[] args) {ITest iTest = new ITest();//报错,不能直接实例化接口}
    

    在这里插入图片描述

    interface ITest {//待实现的方法void func();
    }class A implements ITest {@Overridepublic void func() {System.out.println("类A实现的func");}
    }class NewTest {public static void main(String[] args) {//接口引用了A类对象ITest iTest = new A();}
    }
    
  2. 接口可以定义变量,且接口的成员变量都是publicstaticfinal修饰的,且接口定义的变量必须手动初始化

    即使我们不写修饰符,成员变量也默认被publicstaticfinal修饰

    public abstract interface ITest {//下面定义的变量都是由 public static final 修饰的(不论是否显性书写或写全)public int a = 1;static int b = 2;final int c = 3;int d = 4;public static int e = 5;static final int f = 6;public final int g = 7;public static final int h = 8;
    }
    
  3. 接口可以定义方法,接口的方法默认是publicabstract修饰的,属于抽象方法,不需要方法体。如果想要在接口中具体实现一个方法,那么它必须是由defaultstatic修饰

    public interface ITest {//以下写法的修饰符都是 public abstract(无论是否写或写全)void func0();public abstract void func1();public void func2();abstract void func3();//被default或static修饰的方法有具体的实现default void func4() {System.out.println("接口中被default修饰的方法有方法体");}static void func5() {System.out.println("接口中被static修饰的方法有方法体");}
    }
    
  4. 实现接口的类,必须重写接口中的所有抽象方法,如果此类不想重写接口中的抽象方法,则它必须由abstract修饰,一旦此类被另一个非抽象类继承,那么这个非抽象类必须重写所有未被重写的抽象方法

    interface IA {//接口抽象方法void abfunc1();
    }abstract class A implements IA {public void myA() {System.out.println("A类特有的方法");}//A类抽象方法abstract void abfunc2();
    }class B extends A {@Overridepublic void abfunc1() {System.out.println("重写IA接口中的抽象方法");}@Overridevoid abfunc2() {System.out.println("重写B类中的抽象方法");}
    }
    
  5. 接口中不能有静态代码块、构造代码块或构造方法

  6. 由于接口的成员方法默认都有public修饰,所以重写后的方法必须是public修饰(重写后的方法的访问权限要大于等于父类)

  7. 上述表述的重写严格来说不准确,不过,语法要求与重写一致(这里不必纠结,只要记住抽象方法要被重写即可)

  8. 接口文件的文件名必须与接口名相同,且接口文件编译后也是.class为后缀的字节码文件


接口的使用

接口不能直接实例化对象,接口的使用需要一个 “实现类” 来 实现 接口中的方法,要用到关键字implements

public classimplements 接口 {//...
}

接口与类之间implements实现关系,父类和子类之间extends继承关系

interface ITest {//待实现的方法void func();
}class A implements ITest {@Overridepublic void func() {System.out.println("类A实现的func");}
}

继承表达的是is A的关系,如狗是动物;接口表达的含义是具有xxx特性,如狗会跑


实现多个接口

Java中不支持多继承,不过一个类可以实现多个接口,这个类需要实现所有接口的抽象方法:

//ISwimming.java
public interface ISwimming {void swim();
}//IRunning.java
public interface IRunning {void run();
}//Dog.java
public class Dog implements IRunning, ISwimming {public String name;public int age;public Dog(String name, int age) {this.name = name;this.age = age;}@Overridepublic void run() {System.out.println(this.name + "正在跑");}@Overridepublic void swim() {System.out.println(this.name + "正在游泳");}
}
  • 一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类

一个类可以继承一个父类并同时实现多个接口:

//Animal.java
public class Animal {public String name;public int age;
}
//IRunning.java
public interface IRunning {void run();
}//ISwimming.java
public interface ISwimming {void swim();
}//Dog.java
public class Dog extends Animal implements IRunning, ISwimming {public Dog(String name, int age) {this.name = name;this.age = age;}@Overridepublic void run() {System.out.println(this.name + "正在跑");}@Overridepublic void swim() {System.out.println(this.name + "正在游泳");}
}
  • 继承与实现都存在时,必须先写extends继承,后写implements实现
  • 对于上面的代码,理解一点:只要一个类实现了如IRunning接口,它就可以run(),而不必是动物。(有些废话,主要是强调接口使用)

接口与多态

Java中,接口可以实现多态,看如下代码:

//IEat.java
public interface IEat {void eat();
}//Animal.java
public class Animal {public String name;public int age;
}//Cat.java
public class Cat extends Animal implements IEat {public Cat(String name, int age) {this.name = name;this.age = age;}@Overridepublic void eat() {System.out.println(this.name + "正在吃猫粮...");}
}//Dog.java
public class Dog extends Animal implements IEat {public Dog(String name, int age) {this.name = name;this.age = age;}@Overridepublic void eat() {System.out.println(this.name + "正在吃狗粮...");}
}//Test.java
public class Test {//体现多态public static void testEat(IEat iEat) {iEat.eat();}public static void main(String[] args) {testEat(new Dog("大哈", 2));//匿名对象testEat(new Cat("小猫", 3));}
}

对于上述代码,我们给同一个方法testEat传入不同的对象CatDog,打印结果不同:

在这里插入图片描述


接口间的继承

接口的继承相当于把所有的接口合并在一起。

接口间可以实现继承

//IExcellentQuality.java
public interface IExcellentQuality {void func1();
}//IKind.java
public interface IKind extends IExcellentQuality {void func2();
}

上述代码逻辑上就是:善良的 是 品质优良的

  • 一个接口继承了另一个接口,子接口不实现父接口的抽象方法,而当一个非抽象类实现了子接口,那么这个类要重写子接口和父接口所有的抽象方法

    public class Person implements IKind {@Overridepublic void func2() {System.out.println("kind");}@Overridepublic void func1() {System.out.println("excellent quality");}
    }
    

Java中,类与类之间不可以实现多继承,但接口与接口之间可以实现多继承

比如以下例子,两栖动物既可以游泳又可以行走:

//IRunning.java
public interface IRunning {void run();
}//ISwimming.java
public interface ISwimming {void swim();
}//IAmphibious.java
public interface IAmphibious extends ISwimming, IRunning {void func();
}

【总结】

  • 一个接口继承了另一个接口,子接口不实现父接口的抽象方法,而当一个非抽象类实现了子接口,那么这个类要重写子接口和父接口所有的抽象方法
  • 接口与接口之间可以实现多继承

抽象类和接口的区别

抽象类中可以包含普通的方法和字段,这些字段和方法可以被子类直接使用(普通方法不需要被重写),而接口中不能定义普通的字段和方法,子类必须重写接口中的所有抽象方法。

在这里插入图片描述

几点具体的区别:

    1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行(除非被defaultstatic修饰)。
    1. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
    1. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。(从 Java8 开始接口中可以定义静态方法)
    1. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

另外,我们补充一下实现接口与继承的区别:

1.不同的关键字,即实现接口(implements),继承(extends);

2.(一个类只能继承一个父类,而一个方法可以实现多个接口) 在面向对象编程的时候只能是单继承,但是实现接口可以有多个,简单点说,就是实现接口可以有好多个,但是继承的中父类只能只有一个,因为父亲只有一个,这说明了继承在Java中具有单根性,子类只能去继承一个父类;

3.在接口中只能定义全局变量和抽象方法,而在继承中可以定义普通的属性、方法等等…

4.(接口中的抽象方法必须被重写,而继承中子类可以选择不重写父类的方法(不考虑父类是抽象类)) 当某个接口被实现的时候,在类中一定要重写接口中的抽象方法,而继承中子类可以选择是否重写父类的方法,不是强制的


以上就是对Java中抽象类和接口的所有介绍了,希望能给大家带来帮助!
接下来将会发布不少博客:Java实现简单的图书管理系统、介绍内部类、介绍String…

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

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

相关文章

【第一节】从C语言到C++

目录 一、面向对象编程 1.早期概念 2.发展与普及 3. 现代发展 二、从C语言到C 1.关于堆内存的使用 2.关于函数重载 3.关于默认参数 4.引用 5.引用参数 6.作用域符号 三、C的输入输出机制 一、面向对象编程 面向对象编程(Object-Oriented Programming&am…

如何进一步缩短Python性能

1、问题背景 给定一个(x,y)处的节点网格,每个节点有一个值(0…255)从0开始。有N个输入坐标,每个坐标在(0…x, 0…y)的范围内。一个值Z,它定义了节点的“邻域”。增加输入坐标及其邻居节点的值。网格边缘之外的邻居被忽略。基准案例&#xff…

产教协同|暴雨AI算力赋能传媒实践教学

近日,“第七届传媒实践教学创新研讨会暨中国高校影视学会实验教学专业委员会年会”在美丽的山城重庆成功举办。本次大会以“拥抱AI,融合共生”为主题,吸引了来自全国200多所高校、30多家企业以及700多位大视听实践教学产学研用各界专家、学者…

Data Lakehouse:你的下一个数据仓库

作者:张友东 StarRocks TSC member/镜舟科技 CTO 数据分析是现代企业和组织决策过程中不可或缺的一部分,数据分析技术经过数十年的发展,需求场景从 BI 报表到数据探寻、实时预测、用户画像等不断丰富,技术架构经历从数据仓库、数据…

【AIGC】GPT-4o技术分析-浅谈

GPT-4o:人工智能技术的全新里程碑 一、引言二、GPT系列版本间的对比分析三、GPT-4o的技术能力分析多模态处理能力速度与性能优化情感理解与表达能力 四、个人整体感受五、结语 一、引言 在人工智能技术的浪潮中,OpenAI再次以其卓越的创新能力引领潮流。近…

15.Redis之持久化

0.知识引入 mysql的事务,有四个比较核心的特性. 1. 原子性 2.一致性 3.持久性 >(和持久化说的是一回事)【把数据存储在硬盘 >持久把数据存储茌内存上>不持久~】【重启进程/重启主机 之后,数据是否存在!!】 4.隔离性~ Redis 是一个 内存 数据库.把数据存储在内存中的…

RFID芯片掼蛋牌:高科技与传统玩法结合,游戏体验焕然一新。

火爆“出圈”的掼蛋,是一种玩法相当鲜明的智力游戏。近年来得到了不少的推广和发展,各地举办了各种掼蛋比赛和活动,吸引了大量的参赛者和观众。此外,一些企业和机构也开始将掼蛋作为一种企业文化或者社交活动的方式,通…

灯下黑”挖出国内知名安全平台某BUF的CSRF漏洞

漏洞复现: 漏洞点在删除文章的地方,首先为了测试先发布一篇文章 发布之后我们可以查看文章,注意url中的一串数字,就是这篇文章的id,如下如: 这里的文章id是“271825”,首先抓一下删除文章的数据…

JavaScript基础(十)

上一篇学了各种数组方法&#xff0c;正好先做个练习回忆一下: 排序并去重 我随便写一组数&#xff0c;要求排好并去掉重复的: var arr [2,8,1,7,2,6,1,5,2,7,6,5]; for (var i0; i<arr.length; i){ for (var ji1; j<arr.length; j){ if(arr[i]arr[j]){ arr.splice(j,1)…

LeetCode 474.一和零

没做出来&#xff0c;最后看了解析&#xff0c;看了半天才懂。 我一开始把这个题当成多重背包来做了&#xff0c;因为有0和1两个参数需要考虑&#xff0c;但是中间很多情况不知道怎么处理。后面看了解析才知道这是个01背包问题&#xff0c;0和1都是一个物品上的属性&#xff0c…

K-means 聚类模型详解

K-means 聚类模型详解 K-means 是一种常用的无监督学习算法&#xff0c;用于将数据集分成 K 个簇。其目标是最小化各个簇内数据点到簇中心的距离平方和。K-means 广泛应用于图像压缩、市场细分、模式识别等领域。 算法步骤 初始化: 随机选择 K 个初始簇中心&#xff08;质心…

【主题广泛|投稿优惠】2024年区块链、网络与物联网国际会议(BNIT 2024)

2024年区块链、网络与物联网国际会议&#xff08;BNIT 2024&#xff09; 2024 International Conference on Blockchain, Networks, and the Internet of Things 【重要信息】 大会地点&#xff1a;深圳 大会官网&#xff1a;http://www.icbnit.com 投稿邮箱&#xff1a;icbni…

揭秘智慧校园:可视化技术引领教育新篇章

随着科技的飞速发展&#xff0c;我们的生活方式正在经历一场前所未有的变革。而在这场变革中&#xff0c;学校作为培养未来人才的重要基地&#xff0c;也在不断地探索与创新。 一、什么是校园可视化&#xff1f; 校园可视化&#xff0c;就是通过先进的信息技术&#xff0c;将学…

永久免费SSL证书领取流程

一、SSL证书的前世今生 起源&#xff1a; SSL证书起源于1994年&#xff0c;当时网景公司&#xff08;Netscape&#xff09;推出了安全套接字层&#xff08;SSL&#xff0c;Secure Sockets Layer&#xff09;协议&#xff0c;这是一种加密通信协议&#xff0c;用于在客户端和服…

武汉城投城更公司与竹云科技签署战略协议,携手构建智慧城市新未来!

2024年5月16日&#xff0c;武汉城投城更公司与深圳竹云科技股份有限公司&#xff08;以下简称“竹云”&#xff09;签订战略合作协议&#xff0c;双方将深入推进产业项目合作。 签约现场&#xff0c;双方围绕产业项目合作方向、路径和内容等进行了全面深入交流。城投城更公司党…

第五届武汉纺织大学ACM程序设计竞赛 个人题解(待补完)

前言&#xff1a; 上周周日教练要求打的一场重现赛&#xff0c;时长五个小时&#xff0c;题目难度还行&#xff0c;除了部分题目前我还写不出来之外&#xff0c;大部分题都写完或补完了&#xff0c;这边给出比赛链接和我的代码&#xff08;有些是队友的&#xff09;和题解。 正…

这些项目,我当初但凡参与一个,现在也不至于还是个程序员

10年前&#xff0c;我刚开始干开发不久&#xff0c;我觉得这真是一个有前景的职业&#xff0c;我觉得我的未来会无限广阔&#xff0c;我觉得再过几年&#xff0c;我一定工资不菲。于是我开始像很多大佬说的那样&#xff0c;开始制定职业规划&#xff0c;并且坚决执行。但过去这…

Midjourney设计服装5步实操分享!(实操干货系列)

2k字讲清楚如何在有限素材的基础上&#xff0c;用MJ随机生成设计服装&#xff0c;附本人实操步骤图~ 灵感来源&#xff1a;既然Midjourney&#xff08;MJ&#xff09;能够参考图片进行绘图&#xff0c;那么&#xff0c;提供一些素材&#xff0c;借由MJ的随机成图来寻找一些服装…

香橙派Kunpeng Pro评测

有幸受邀评测香橙派与华为鲲鹏在2024年5月12刚刚联合发布的新品香橙派Kunpeng Pro。 本文将从软硬件、AI算法测试等角度简单分享一下博主拿到板子以来感受与所做的评测。 一、硬件 香橙派Kunpeng Pro实物图 处理器方面&#xff0c;香橙派Kunpeng Pro采用了4核64位armv8架构处…

生产者延迟消息和重试机制

messageDelayLevel1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h 延迟消息级别public PutMessageResult putMessage(final MessageExtBrokerInner msg) {//事务消息处理if (tranType MessageSysFlag.TRANSACTION_NOT_TYPE|| tranType MessageSysFlag.TRANSACT…