- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java 抽象类与接口的对比由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
其实说实话,没有多大的可比较性,它们是完全不同的两个东西,它们的抽象不在同一个层级上。但是为了让大家更好的理解,还是做一个比较吧,毕竟它们都很抽象(233).
首先是语法层面上的对比 。
1)抽象类跟接口都不能被实例化,因为它们都很虚嘛。但是在访问权限上,两者有一定的区别.
a、抽象类中的抽象方法(其前有abstract修饰)不能用private、static、synchronized、native访问修饰符修饰。理由很简单,容我慢慢道来.
抽象方法是没有方法体的,它的目的就是用来继承的,所以如果使用private修饰,不就不能被继承了吗?这就违背了它的设计初衷了,所以不能用private来修饰抽象方法。至于static,用它来修饰的方法可以不实例化就可以直接调用,但是抽象方法没有方法体,使用static修饰就没有意义了。synchronized是用来加锁的,如果修饰类中的方法的话,就相当于用this变量锁,但是抽象类是不能被实例化的,抽象方法也不是在本类中实现而是在子类中实现的,所以锁应该是子类所属,所以抽象方法不能用synchronized关键字修饰;至于native,这个跟abstract关键字本身就是冲突的,abstract声明方法交给子类实现,而native则是交给本地操作系统实现,如果同时出现,那就相当于把实现交给子类,又交给本地操作系统,那最后到底由谁来实现呢?
综上所述,抽象类中的抽象方法只能用public和protected修饰.
b.接口中的方法全部为public abstract修饰,不能使用其他修饰符,而且默认情况(不加任何修饰符)下,也是public abstract的,因为接口只能被类实现,不能被类继承,所以不能使用protected修饰,但接口是可以继承接口的.
2)抽象类跟普通类的唯一区别就是不能被实例化,可以有抽象方法,所以它可以有构造函数,静态方法,静态代码块,可以有普通的成员变量和方法。但是接口就不一样了,接口只能声明public abstract的方法和public static final的成员变量.
3)抽象类本质上还是一个类,只能单继承,一个类只能继承一个抽象类,但可以实现多个接口.
其次是概念上的比较 。
1)抽象类跟接口的抽象角度不一样,抽象类一般是对某些具有相似属性和方法的类进行抽象,抽象出一个统一的父类。而接口则更多的是多一组特定行为的抽象,关注的是行为,而具有这些行为的类之间可能并没有太大的关联性.
比如说,飞机能上天,鸟能上天,你要是厉害一点,应该也能上天(逃),但显然两者之间的关联度不大,如果硬是要给它们插上一个公共的父类的话,似乎不合情理,看起来就像这样:
1
2
3
|
public
abstract
class
Flyer {
public
abstract
void
fly();
}
|
然后定义两个类来继承它:
1
2
3
4
5
6
7
|
public
class
Airplane
extends
Flyer {
@Override
public
void
fly() {
System.out.println(
"Airplane is flying."
);
}
}
|
1
2
3
4
5
6
7
|
public
class
Bird
extends
Flyer {
@Override
public
void
fly() {
System.out.println(
"Bird is flying."
);
}
}
|
好的,现在写一个测试类:
1
2
3
4
5
6
7
8
9
10
|
public
class
Test {
public
static
void
main(String[] args) {
Flyer[] flyer =
new
Flyer[
2
];
flyer[
0
] =
new
Airplane();
flyer[
1
] =
new
Bird();
for
(Flyer f:flyer){
f.fly();
}
}
}
|
运行结果如下:
Airplane is flying. Bird is flying. 。
乍眼一看,好像运行良好,但是仔细想想,将两个关联度很低的类强行插上一个父类,似乎有些不妥,毕竟飞机跟鸟除了都能飞以外,基本没有什么相似的地方了,而且两者的飞行方式,飞行速度和高度都相去甚远,也就是说除了这个fly的方法,其他方法都要在各自的子类实现,而且一个类只能继承一个抽象类,所以Bird类和Airplane类就无法再继承其他类了,这样就反而限制了程序的灵活性。所以,这种时候,还是比较适合使用接口:
1
2
3
4
|
public
interface
IFlyable {
//声明Fly方法
void
fly();
}
|
而此时只需要将Airplane类和Bird类的extends Flyer改成implement Flyable即可.
1
2
3
4
5
6
7
8
|
public
class
Airplane
implements
IFlyable {
//实现Fly方法
@Override
public
void
fly() {
System.out.println(
"Airplane is flying."
);
}
}
|
1
2
3
4
5
6
7
|
public
class
Bird
implements
IFlyable {
//实现Fly方法
@Override
public
void
fly() {
System.out.println(
"Bird is flying."
);
}
}
|
再修改一下Test类:
1
2
3
4
5
6
7
8
9
10
|
public
class
Test {
public
static
void
main(String[] args) {
IFlyable[] flyer =
new
IFlyable[
2
];
flyer[
0
] =
new
Airplane();
flyer[
1
] =
new
Bird();
for
(IFlyable f:flyer){
f.fly();
}
}
}
|
输出如下:
Airplane is flying. Bird is flying. 。
也许从这个栗子还没法明显的看出两者的区别,那么我们再换一个栗子,人可以坐飞机,可以坐火车,还可以坐汽车,只要它们有载人功能即可,那用接口实现如下:
1
2
3
4
5
|
public
interface
ICarryPassenger {
//声明载客方法
void
carry(Passenger passenger);
}
|
定义一个乘客类,用姓名来区分各个乘客.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public
class
Passenger {
private
String name;
//乘客姓名
public
Passenger(String name){
this
.name = name;
}
public
String getName() {
return
name;
}
//出行方式
public
void
travelBy(ICarryPassenger ic){
ic.carry(
this
);
}
}
|
分别定义汽车类,火车类,飞机类,它们都实现ICarryPassenger接口,飞机还可以实现IFlyable接口(虽然没有用到。。):
1
2
3
4
5
6
7
8
9
10
11
12
|
public
class
Car
implements
ICarryPassenger {
int
passengerNum;
//实现carry方法
@Override
public
void
carry(Passenger passenger) {
System.out.println(
"Passenger:"
+passenger.getName()+
" travel by Car."
);
passengerNum++;
System.out.println(
"Car carries: "
+passengerNum+
" passenger."
);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
|
public
class
Train
implements
ICarryPassenger {
int
passengerNum;
@Override
public
void
carry(Passenger passenger) {
System.out.println(
"Passenger:"
+passenger.getName()+
" travel by Train."
);
passengerNum++;
System.out.println(
"Train carries: "
+passengerNum+
" passenger."
);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public
class
Airplane
implements
IFlyable,ICarryPassenger{
private
int
passengerNum;
//乘客数量
//实现Fly方法
@Override
public
void
fly() {
System.out.println(
"Airplane is flying."
);
}
//实现carry方法
@Override
public
void
carry(Passenger passenger) {
System.out.println(
"Passenger:"
+passenger.getName()+
" travel by Airplane."
);
passengerNum++;
System.out.println(
"Airplane carries: "
+passengerNum+
" passengers."
);
}
}
|
好的,现在我们写一个测试类来进行测试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public
class
Test {
public
static
void
main(String[] args) {
//有6个乘客想要去旅游,对于旅行方式没有侧重,随机分配交通工具
Random random =
new
Random();
Passenger[] passengers =
new
Passenger[
6
];
//声明6个乘客
for
(
int
i=
0
;i<
6
;i++){
passengers[i] =
new
Passenger(
"Passenger["
+i+
"]"
);
}
ICarryPassenger[] icp =
new
ICarryPassenger[
3
];
//声明3种交通方式
icp[
0
] =
new
Airplane();
icp[
1
] =
new
Car();
icp[
2
] =
new
Train();
for
(
int
i=
0
;i<
6
;i++){
passengers[i].travelBy(icp[random.nextInt(
3
)]);
}
}
}
|
输出如下:
Passenger:Passenger[0] travel by Airplane. Airplane carries: 1 passengers. Passenger:Passenger[1] travel by Train. Train carries: 1 passenger. Passenger:Passenger[2] travel by Airplane. Airplane carries: 2 passengers. Passenger:Passenger[3] travel by Car. Car carries: 1 passenger. Passenger:Passenger[4] travel by Train. Train carries: 2 passenger. Passenger:Passenger[5] travel by Airplane. Airplane carries: 3 passengers. 。
因为飞机跟火车,汽车之间并没有太大关联,显然无法直接抽象出父类,它们仅有相同的行为,那就是载客,所以使用接口是最合适的.
至此,本篇讲解完毕,想必通过这一篇的讲解,对于抽象类和接口的区别应该有了更好的理解吧,如果有更好的栗子,欢迎大家留言交流,也欢迎大家继续关注.
以上就是Java 抽象类与接口的对比的详细内容,更多关于Java 抽象类与接口的资料请关注我其它相关文章! 。
原文链接:https://cloud.tencent.com/developer/article/1016598 。
最后此篇关于Java 抽象类与接口的对比的文章就讲到这里了,如果你想了解更多关于Java 抽象类与接口的对比的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!