JavaSE-- 抽象类和接口(上)

news/2024/11/6 13:55:16/

抽象类和接口(上)

一丶抽象类

什么是抽象类?
顾名思义,首先抽象类它是一个类,那么抽象怎样来理解呢?我们对抽象的定义就是难以理解的,难以用言语形容的。所以依据这里,给出了如下的定义:

在类中没有足够的信息来描绘一个具体的对象,这样的类就叫抽象类。

再具体:

抽象类是一个自下而上的抽象过程,其提供了通用实现,是事物的抽象。我们在实现类的过程中,可以发现有些类有几乎相同的实现,我们把这些几乎相同的实现抽取出来成为抽象类。然后如果有一些差异,那么我们支持抽象方法自定义实现。

写法

抽象类的写法很是简单(具体如下):

public abstract class Persion {//使用abstract关键字来定义一个抽象类public String name;public int age;public Persion(String name,int age) {this.name = name;this.age = age;}public void run(){System.out.println(name + "正在奔跑");}abstract void eat();//使用abstract关键字来定义抽象方法abstract public void body();
}

在这里,我定义了一个“人”这样一个抽象类。我们每个人都会使用两条腿进行奔跑,但是由于南北方的差异和气候环境,人们的饮食习惯,还有身材比例各不相同,所以这里用抽象方法仅仅声明有这个特性。

特性

我们定义抽象类肯定是有许多的规则,具体有哪些,接下来进行分析。

1. 抽 象 类 不 能 直 接 实 例 化 对 象 \color{red}{1.抽象类不能直接实例化对象} 1.

先放代码:
在这里插入图片描述可以看到,这里我尝试定义一个Persion的对象,但是报出来了一个错误:Persion是抽象的,不能被实例化。

2. 抽 象 方 法 不 能 是 p r i v a t e 的 \color{red}{2. 抽象方法不能是 private 的} 2.private

在继承关系当中,虽然子类也继承了父类的私有制方法,但是它不能进行访问,所以当把方法定义为private的时候,这个时候这个方法不能被抽象类的子类进行重写。同理: 抽 象 方 法 不 能 是 s t a t i c 、 p r i v a t e , f i n a l 修 饰 的 \color{blue}{抽象方法不能是static、private,final修饰的} staticprivatefinal
接下来进行验证:
首先,我定义一个“南方人类”和“北方人类”。

public class SouthPeople extends Persion{//定义南方人类public SouthPeople(String name, int age) {super(name, age);}@Overridevoid eat() {System.out.println(name + "吃面条");}@Overridepublic void body() {System.out.println(name + "身体小巧");}
}
public class NorthPeople extends Persion{//定义北方人类public NorthPeople(String name, int age) {super(name, age);}@Overridevoid eat() {System.out.println(name + "吃面条");}@Overridepublic void body() {System.out.println(name + "身体小巧");}
}

那么,接下来我们对抽象方法进行测试,看看它会有哪些错误。

1. 关 于 权 限 修 饰 符 问 题 \color{violet}{1.关于权限修饰符问题} 1.
首先是对于private,很明显报了错误,说abstract和private不能同时出现

在这里插入图片描述在这里插入图片描述
再接着对于default 和不写
在这里插入图片描述
这里可以看出,不写和default是两码事,不写可以,但是default就不行。
这是因为:
抽 象 方 法 不 加 权 限 修 饰 符 的 时 候 默 认 是 p u b l i c \color{blue}{抽象方法不加权限修饰符的时候默认是public} public

然后最后对于protect
在这里插入图片描述

此刻并没有报错,所以是可以的。
2. 关 于 s t a t i c 问 题 \color{violet}{2.关于static问题} 2.static
如果给一个方法加上了static,那么就是静态方法,此时这个方法就是属于类的行为,不是对象的。
在这里插入图片描述
如果加上了static,那么编译器会报错,static和abstract不能同时出现。

3. 子 类 要 重 写 抽 象 类 中 所 有 的 抽 象 方 法 \color{red}{3.子类要重写抽象类中所有的抽象方法} 3.

首先,抽象类一定要被继承,并且子类要重写抽象类中所有的抽象方法
这里用“北方人类”进行测试。
在这里插入图片描述
我这里去掉了NorthPeople{ }中的body()抽象方法,这里出现了异常:NorthPeople必须被声明为抽象类或者重写Persion{ }类中的body()方法。
也就是说:
在这里插入图片描述
如果子类没有重写抽象类中所有的抽象方法,那么这个子类也要被声明为抽象类

好处

作为抽象类,子类要对父类方法进行重写,但是如果我不用抽象类,子类也可以对父类方法进行重写,并且对应的功能我也有,那使用抽象类的意义在哪里呢?

其实就相当于多了一层代码的效验器。

具体解释如下:
如上所示,很多工作是需要子类去完成的,而不是父类,如果这个时候我们不使用抽象类的时候,错误的使用了父类,那么此时编译器不会报错。但如果是抽象类的话那么就会报错。
所以:

使用抽象类的意义就在于效验,和final的使用意义相近,final是为了防止用户误
修改,而abstract是为了防止错误的使用。

二丶接口

什么是接口?
接口在生活中随处可见,USB接口,公牛插座接口,手机充电线接口…
那么在JAVA中,什么是接口?

接口是自上而下的抽象过程,其对某些行为进行了规范,是行为的抽象,可以看成是一种引用数据类型。如果说,我需要某一行为,那么我就去实现相对应的接口,但是具体怎么实现,由我自己说了算。

写法

接口的写法和抽象类类似,但是把abstract关键字换成了interface。这里呢,我设计了一个Sing{ }接口,来对此进行讲解。

public interface Sing {//定义一个Sing接口void sing();
}

这里的话对于写法进行规范:

  1. 创建接口时, 接口的命名一般以大写字母 I 开头.
  2. 接口的命名一般使用 “形容词” 词性的单词.
  3. 阿里编码规范中约定, 接口中的方法和属性不要加任何修饰符号, 保持代码的简洁性.

使用

就像定义中说的,我们需要某个行为,那么我们就去实现相对应的接口。
在这里插入图片描述
在这里插入图片描述
那么接下来,我们就创建一个对应的对象,来对上述内容进行验证(这里补全上面的代码):

public class TestAbstract {//这是验证抽象类和接口的public static void main(String[] args) {NorthPeople p1 = new NorthPeople("北方人张三",18);p1.eat();p1.sing();SouthPeople p2 = new SouthPeople("南方人李四",18);p2.eat();p2.sing();}
}

运行结果如下:
在这里插入图片描述

特性

1. 不 能 直 接 n e w 接 口 的 实 例 \color{red}{1.不能直接new接口的实例} 1.new

什么意思?就是说:

虽然接口是一种引用数据类型,但是不能直接new出他的对象。

代码如下:

在这里插入图片描述
这里报错,Sing是抽象的,不能直接实现。

2. 关 于 接 口 的 修 饰 符 \color{red}{2.关于接口的修饰符} 2.

接口中每一个方法都是public的抽象方法, 即接口中的方法会被隐式的指定为 public abstract(只能是public abstract,其他修饰符都会报错)
在这里插入图片描述

在这里插入图片描述

然后来看一下正确的形式:
在这里插入图片描述
这里的话public abstract是灰色的,意味着他们其实都是可以省略的
在这里插入图片描述

2. 关 于 接 口 的 成 员 属 性 \color{red}{2.关于接口的成员属性} 2.

接口中不能有成员变量,只能有常量,如果说要定义一个变量,那么必须加上 public static final对它常量化!!
具体如下:
在这里插入图片描述
一旦定义了之后,不能修改!!因为被final化了。

3. 接 口 抽 象 方 法 不 能 有 方 法 体 \color{red}{3.接口抽象方法不能有方法体} 3.

这里是什么意思呢?就是说,接口定义的方法如果是抽象方法,那么这个方法不能有方法体,相对应的实现应该在子类中完成。
在这里插入图片描述
编译器报错如上:接口抽象方法不能有方法体
再接着继续,如果说想要有方法体,那么就不能是抽象方法,这个时候我们就要修改,上面我们说了: 接 口 中 抽 象 方 法 的 修 饰 符 必 须 是 p u b l i c a b s t r a c t , 那 么 我 们 就 要 接口中抽象方法的修饰符必须是public abstract, 那么我们就要 publicabstract 把 他 改 为 d e f a u l t 把他改为default default
这 里 注 意 , 是 d e f a u l t , 不 是 不 写 ! 不 是 不 写 ! 不 是 不 写 ! ! \color{red}{这里注意,是default,不是不写!不是不写!不是不写!!} default,

具体如下:
在这里插入图片描述
那么这样定义的意义在哪里呢?

很多时候,我们可能要对抽象方法进行修改,但是呢一旦新增或者减少抽象方法那
么就要对所有其下的子类进行修改,如果子类少了还好说,一旦多了之后,那么无
疑是一个很繁琐的工程,这个时候,我们就要用到default定义的非抽象方法,因
为是非抽象方法,所以子类不需要对该方法进行重写的同时又可以访问到该方法。

5. 接 口 编 译 后 字 节 码 文 件 的 格 式 是 . c l a s s \color{red}{5. 接口编译后字节码文件的格式是.class} 5..class

关于这一点的验证首先我们运行相对应的代码。
然后打开对应项目下的out文件夹,然后找到对应的.class文件。

在这里插入图片描述
在这里插入图片描述

6. 重 写 接 口 的 方 法 时 不 能 用 d e f a u l t 修 饰 \color{red}{6.重写接口的方法时不能用default修饰} 6.default

在这里插入图片描述
这里的话,应该是说子类修饰符权限要大于等于父类。
在这里插入图片描述
这里意思是说:此修饰符仅仅可以在接口中被使用

其实不仅仅是default,因为接口中的抽象方法修饰符一般是public,所以呢,子类的修饰符也只能public了。

7. 接 口 中 不 能 有 静 态 代 码 块 和 构 造 方 法 。 \color{red}{7. 接口中不能有静态代码块和构造方法。} 7.

首先, 接 口 不 是 类 ! ! ! \color{red}{接口不是类!!!} ,所以不能有构造方法,因为它想初始化成员变量也没有变量让他初始化呀。然后对于静态代码块,静态代码块初始化成员变量,这一点和上面同理。

先是静态代码块:
在这里插入图片描述

再接着对于构造代码块:
在这里插入图片描述

多继承

接口允许多继承,但是类只能单继承,为什么?

如果说类之间运行多继承,那么当两个父类其中的某种方法完全相同时,子类不知
道要对那个父类的方法进行重写,但是如果是接口就没有这种顾虑,因为接口没有
方法体,不论写哪一个都不会冲突,不会造成额外影响!

一个类可以继承多个接口,那么,我们创建一个新的包来对此进行验证。

public class Animal {//这是父类动物类,所有动物共用的模板public String name;public int age;public String gender;public Animal(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}
}public interface Running {//接口跑:定义跑的行为void run();
}public interface Jump {//接口跳:定义跳这个行为void jump();
}public interface Swim {//定义游泳这个行为void swim();
}

接下来定义具体的动物类:

public class TianE extends Animal implements Running,Jump,Swim{//天鹅类public TianE(String name, int age, String gender) {super(name, age, gender);} @Overridepublic void jump() {System.out.println(name + "身体一摇一摆的跳");}@Overridepublic void run() {System.out.println(name + "小脚掌噗嗤的跑");}@Overridepublic void swim() {System.out.println(name + "在水里开心的游");}
}public class Dog extends Animal implements Running,Jump,Swim{//狗类public Dog(String name, int age, String gender) {super(name, age, gender);}@Overridepublic void jump() {System.out.println(name +"两条狗腿开心的蹦");}@Overridepublic void run() {System.out.println(name + "撒开狗腿开心的跑");}@Overridepublic void swim() {System.out.println(name + "漏出狗头开心的游");}
}

然后接下来我们对这个多继承进行实验:
在这里插入图片描述
具体操作如上。
这里的话有一个点需要特别注意:

一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。

接口之间的继承

接口和接口之间也是可以继承的。这里的继承,是多继承,使用extends关键字,代码示例如下(仅展示部分关键代码):


public interface RunningFu{void run();
}public interface Running extends RunningFu{//接口跑:定义跑的行为}

这样的话,在实现类中并没有报错。
在这里插入图片描述


http://www.ppmy.cn/news/195565.html

相关文章

vue实现商城列表渲染

需求: 利用vue实现商城列表渲染 所需数据如下: mockData: [{"id": 1,"img": "https://img13.360buyimg.com/n7/jfs/t1/204395/30/8748/221924/6153df6bE11359c8c/f0a78ca2e00b7116.jpg","text": "亿匚鑫…

android usb充电电流,插线板上的USB口能不能给手机充电?

目前不少插线板都紧随智能时代的步伐,加上USB充电功能,比如小米、公牛、奥睿科等著名品牌都推出了类似的产品。不过不少用户对这类插线板仍抱有一丝怀疑:插线板的USB接口真的可以代替充电器给手机充电吗? 现在市面上主流的手机在手…

Adapter模式(适配器模式)

模式简介 适配器模式在生活中也比较常见,例如我们的手机充电头就是一个适配器,我们无法将家庭电源直接与手机进行连接,因为这可能带来较大的安全隐患,并且也不太便利,所以我们需要一个中间的适配器,这个适…

互联网日报 | 8月9日 星期一 | 字节跳动否认重启上市计划;TikTok全球下载量去年居首;中国代表团38金32银18铜收官...

今日看点 ✦ 东京奥运会闭幕,中国代表团38金32银18铜圆满收官 ✦ 高德地图公交出行新增同城火车路线,首批上线30多城 ✦ 最快4小时出结果,百度健康核酸检测覆盖全国百余城市 ✦ 特斯拉西宁首个充电站开放,实现中国32个省会城市充电…

国家知识产权局宣告易百珑自发电专利权有效

2021年11月29日和30日,中国国家知识产权局专利复审委员会先后宣告易百珑的两项基础专利的专利权维持有效,这奠定了易百珑科技在微能量收集与自发电技术领域的翘楚地位。 被维持有效的专利故事还得从十多年前开始讲述。2009年3月易百珑成立电工实验室&…

赛微微电启动上市发行:生产依赖外协加工厂商,市盈率偏高

4月13日,模拟集成电路供应商——广东赛微微电子股份有限公司(下称“赛微微电”,SH:688325)启动在上交所科创板上市发行申购。这意味着,赛微微电将在不久后实现在科创板挂牌上市。 据贝多财经了解,赛微微电…

结构型设计模式

结构型设计模式目的是将现有的类或结构组合到一起形成更强大的结构。结构型设计模式共7种分别为适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式、代理模式。 一、适配器模式 顾名思义适配器模式是将原本不匹配的两个东西适配到一起使用,以三孔插座…

什么牌子的台灯对孩子的视力好?618好用性价比高的护眼台灯

孩子的视力一直都是困扰家长的大问题了,随着科技发展速度,现在的儿童玩电子产品的时间增多了不少,家长应该合理的安排好时间,不然再好的的台灯也不起作用的,而适合孩子的台灯,还是护眼台灯最有效了&#xf…