热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java基础——抽象类和接口

抽象类和接口在实际的项目中,整个项目的代码一般可以分为结构代码和逻辑的代码。就像建造房屋时,需要首先搭建整个房屋的结构,然后再细化房屋相关的其它的结构,也像制造汽车时,需要首先制作汽车的框架,然后才是
抽象类和接口
在实际的项目中,整个项目的代码一般可以分为结构代码和逻辑的代码。就像建造房屋时,需要首先搭建整个房屋的结构,然后再细化房屋相关的其它的结构,也像制造汽车时,需要首先制作汽车的框架,然后才是安装配件以及美化等工作。程序项目的实现也遵循同样的道理。在项目设计时,一个基本的原则就是——“设计和实现相分离”。也就是说结构代码和逻辑代码的分离,就像设计汽车时只需要关注汽车的相关参数,而不必过于关心如何实现这些要求的制作。程序设计时也是首先设计项目的结构,而不用过多的关系每个逻辑的代码如何进行实现。前面介绍的流程控制知识,主要解决的是逻辑的代码的编写,而类和对象的知识,则主要解决结构代码的编写。那么还有一个主要的问题:如何设计结构代码呢?这就需要使用下面介绍的抽象类和接口的知识了。
抽象类
抽象类(Abstract Class)是指使用abstract 关键字修饰的类,也就是在声明一个类时加入了abstract 关键字。抽象类是一种特殊的类,其它未使用abstract 关键字修饰的类一般称作实体类。例如:
public abstract class A{
        public A(){}
}

抽象方法(Abstract Method)是指使用abstract 关键字修饰的方法。
抽象方法是一种特殊的方法,其它未使用abstract 关键字修饰的方法一般称作实体方法。
public abstract void test();
抽象类和实体类相比,主要有以下两点不同:
★抽象类不能使用自身的构造方法创建对象(语法不允许)
例如下面的语法是错误的:
A a = new A();
但是抽象类可以声明对象,例如下面的代码是正确的:
A a;
A a1,a2;
只是声明出的对象默认都是null 的,无法调用其内部的非静态属性和非静态方法。
说明:抽象类可以使用子类的构造方法创建对象。
★抽象类内部可以包含任意个(0 个、1 个或多个)抽象方法
抽象类内部可以包含抽象方法,也可以不包含抽象方法,对于包含的个数没有限制。而实体类内部不能包含抽象方法。
在抽象类内部,可以和实体类一样,包含构造方法、属性和实体方法,这点和一般的类一样。
抽象方法和实体方法相比,主要有以下几点不同:
★抽象方法没有方法体
也就是说在声明抽象方法时,不能书写方法体的{},而只能以分号结束方法。
下面是实体方法和抽象方法声明的比较:
抽象方法声明:
public abstract void test(int a);
实体方法声明:
public void test(int a){
        方法体
}

★抽象方法所在的类必须为抽象类
也就是说,如果抽象方法声明在一个类内部,则该类必须为抽象类。(说明:抽象方法也可以出现在接口内部,这个将在后续进行介绍)。这样,在继承时,如果继承的类是抽象类,而该抽象类中还包含抽象方法时,则该子类必须声明成抽象类,否则将出现语法错误。如果子类需要做成实体类的话,则必须覆盖继承的所有抽象方法。这个是抽象类最核心的语法功能——强制子类覆盖某些方法。
介绍了这么多抽象类和抽象方法的知识以后,那么抽象类有什么用途呢?
抽象类的用途主要有两个:
★严禁直接创建该类的对象
如果一个类内部包含的所有方法都是static 方法,那么为了避免其它程序员误用,则可以将该类声明为abstract,这样其它程序员只能使用类名.方法名调用对应方法,而不能使用对象名.方法名进行调用。
这样的类例如API 中的Math类说明:配合final 关键字使用,将必须该类被继承,这样将获得更加完美的效果。
★强制子类覆盖抽象方法
这样可以使所有的子类在方法声明上保持一致,在逻辑上也必须将方法的功能保持一致。例如游戏中设计类时,设计了怪物类以及相关的子类,每个怪物类都有移动方法,但是每种怪物的移动规则又不相同,这样通过使每个怪物类的移动方法的声明保持一致,方便调用。可以参看前面多态部分的介绍获得更多的关于调用统一知识。
这是抽象类最主要的用途。就像现实社会中,各种银行网点保持统一的装修风格,各种快餐店(肯德基、麦当劳等)保持统一的装修甚至风味,这样便于生活中的识别。通过让存在继承关系的类中功能一样(但是内部实现规则不同)的方法声明成一样的,方便多态的使用。
那么什么时候在设计时使用抽象类呢?这个问题参看一下抽象类的用途自然就知道了。关于抽象类的知识先介绍这么多,下面介绍接口的知识,最终将对抽象类和接口进行一下比较。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
接口
接口(Interface)是一种复合数据类型。
接口就是一个纯粹用来设计的数据类型,在接口这种数据类型中,只能书写两类声明的结构:
★常量数据
所有的常量数据都是public static 的。如果声明时不书写则系统将自动添加这两个修饰符。
抽象方法
接口中的所有方法都只在逻辑上规定该方法的作用,而不能书写方法体。所有接口中的方法都是public abstract 的,如果声明时不书写则系统将自动添加这两个修饰符。
其中接口中的数据是常数,以后不能改变,而方法只是规定要做什么,而不去规定如何进行实现。这样接口就很方便设计人员进行设计,而不必过多的关系对应的方法如何在逻辑上进行实现。
接口声明的语法格式如下:
访问控制符    interface    接口名    [extends     父接口名1,    父接口名2……]{
        常量声明
        方法声明
}
和类的声明一样,访问控制符只能使用public 和默认的。声明时使用interface 关键字声明接口,接口可以继承其它的接口,使用extends 关键字进行继承,多个接口名之间使用逗号进行分隔。和类的集成一样,子接口继承父接口中所有的常量数据和方法,子接口的对象也是父接口的对象。
注意:和抽象类一样,接口只能声明对象,而不能创建对象。接口声明的示例代码如下,
例如声明一个USB 接口来代表实际使用中的USB 结构:
public interface USB{
        /**电压*/
        public static final int V = 5;
        /**读取数据*/
        public abstract byte[] readData();
        /**写入数据*/
        public abstract void writeData(byte[] data);
}
该接口中规定电压常量为5V,声明了两个方法,要求实现USB 时必须实现这样两个方法,至于如何实现这里不做规定。这样这个数据类型就只是设计上的说明,而不牵扯具体的实现,这样在项目中使用时则比较通用。
从这点来看,接口类似于现实中使用的各个国家标准,标准中只规定该类型最终需要达到的标准,而不规定如何实现,各个厂商可以根据自己的产品工艺实现该要求即可。
在实际的项目中,设计接口需要对于项目的整体有比较深刻的了解和认识,这样才可以设计出需要的接口结构,关于接口的设计这里不作太深入的论述。如果需要更深刻的了解设计的结构, 
一般声明对应的类来实现接口,实现接口的语法为:
访问控制符    [修饰符]     class     类名    [extends 父类名]    implements     父接口名1,    父接口名2……
实现接口的语法位于类声明中,位于继承声明的后面,使用implements关键字代表实现,后续是需要实现的接口的名称,一个类可以实现任意多个接口。
实现接口和继承类很类似,声明的类称作接口的子类,接口为该类的父接口,子类中继承父接口中所有的数据和方法,因为接口中所有的方法都是抽象方法,所以如果子类中不实现(覆盖)父接口中的方法,则该类必须声明为抽象类。
例如计算机实现了USB 接口,则示例代码如下:
public class Computer implements USB{
        /**内存容量*/
        int memorySize;
        public abstract byte[] readData(){
        //读数据的逻辑
        }
        public abstract void writeData(byte[] data){
        //写数据的逻辑
        }
}

这里,Computer 类实现了前面的USB 接口,在Computer 类内部可以书写和Computer 类相关的属性、方法和构造方法,这里对于实现接口没有影响,而因为实现了USB 接口,则必须覆盖USB 接口中的readData 和writeData 抽象方法,至于方法内部的代码,则根据逻辑的需要进行实现,从而实现接口中要求实现的功能。
类似的,也可以使一个数码相机实现USB 接口,则实现的示例代码为:
public class DigitalCamera implements USB{
        /**厂商名称*/
        String vendorName;
        public abstract byte[] readData(){
        //读数据的逻辑
        }
        public abstract void writeData(byte[] data){
        //写数据的逻辑
        }
}

在该类中,也可以根据该类的需要实现USB 接口中规定的功能,至于如何实现则很可能和Computer 类不同。这样,虽然Computer 类和DigitalCamera 类自身原来的功能不同,但是都可以通过实现USB 接口而实现同样的功能,这样单纯的从是否支持USB 功能来看,这两个类的实现是一样的。按照面向对象的术语来说,这被称作屏蔽了类的类型之间的不同,保证了程序的通用性。
由于实现接口时,不限制实现的接口的数量,则任何一个类都可以实现任意多个接口,这样就使类的通用性获得了极大的增强,很方便类的对象之间的匹配。就像现实中USB 接口规范方便了多种不同设备之间的互联一样。在语法上,实现了接口的对象可以使用子类的构造方法进行创建,这样又很适合多态的结构,可以说接口的出现,使多态的特性更容易的进行实现。
在实际项目中,通过使用一定的接口,使得很多类的对象在实现某种类型的功能时,方法的声明是统一的,便于程序的调用和管理,利于程序项目的扩展。所以在现在的面向对象编程领域中,存在着另外的一个方向——面向接口的编程,其实很多Java 的技术都是这样进行实现的,例如JDBC 部分。由于抽象类和接口的功能比较类似,后续将对于抽象类和接口进行一系列的比较,方便项目设计时的取舍。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
抽象类和接口的比较
抽象类和接口都是进行面向对象设计时专用的设计结构,在实际进行项目设计时,经常需要考虑的问题就是——“使用抽象类还是接口”?下面通过对于抽象类和接口进行简单的比较,熟悉两者之间的区别和联系,从而在实际设
计时使用恰当的结构。
①:什么时候使用抽象类或接口?
当设计中为了规范类中方法声明的结构(即类的行为)时,使用抽象类或接口。也
就是强制子类对外部提供统一的方法声明时,使用抽象类或接口。
②:.抽象类和接口的区别(不同点)
★抽象类是类,而接口是接口。
因为抽象类是一个类,所以类内部可以包含的内容(构造方法、方法和属性等)在抽象类内部都可以存在,当然抽象类也受到类的单重继承的限制。而接口是接口类型,所以接口内部只能包含常量属性和抽象方法,但是一个类可以实现多个接口,所以接口不受类的单重继承的限制。
抽象类内部可以包含实体方法,而接口不能
抽象类是一个类,所以在抽象类内部既可以包含抽象方法也可以包含实体方法,而接口内部的每个方法都必须是抽象方法。
抽象类可以继承类,而接口不能
抽象类是一个类,所以在设计时可以使抽象类继承其它的类,在已有类的基础上进行设计,但是接口不能继承类。
③:抽象类和接口的联系(相同点)
抽象类和接口都可以声明对象,但是都只能使用子类的构造方法进行创建。
抽象类和接口内部都可以包含抽象方法。按照Java 语言的语法,子类在继承抽象类或实现接口时,都必须覆盖这些抽象方法,否则必须声明为抽象类。
抽象类和接口都可以代表一种类型,从而可以统一子类对象的类型,获得良好的可扩展性。
④:什么时候使用抽象类?
当满足以下的条件时,最好使用抽象类进行设计:
子类不继承其它父类
子类中存在完全相同的功能实现的方法
子类中存在相同的属性
设计出的结构需要继承其它类当需要满足d 条件时,只能使用抽象类,否则也可以考虑使用接口实现。
⑤:什么时候使用接口?
当满足以下的条件时,最好使用接口进行设计:
子类已经继承了其它父类
子类中不存在完全相同的功能实现方法
子类中不存在相同的属性
设计出的结构不需要继承其它类当需要满足a 条件时,只能使用接口,否则也可以考虑使用抽象类实现。
⑥:抽象类和接口的其它用途
禁止创建该类的对象时,可以把该类声明为抽象类。
当需要存储大量的常量数据,而这些常量数据将会在项目中的多个类之间使用时,可以使用接口。
当需要统一具有某种功能的类的对象时,可以使用接口。例如Serializable 接口。当然,只有经过大量的系统设计训练以后,才可以更加深刻的理解抽象类和接口的区别和联系,从而更加自如的进行选择。另外,需要说明的是,不是每个项目中都必须使用抽象类或接口的。

推荐阅读
  • Final关键字的含义及用法详解
    本文详细介绍了Java中final关键字的含义和用法。final关键字可以修饰非抽象类、非抽象类成员方法和变量。final类不能被继承,final类中的方法默认是final的。final方法不能被子类的方法覆盖,但可以被继承。final成员变量表示常量,只能被赋值一次,赋值后值不再改变。文章还讨论了final类和final方法的应用场景,以及使用final方法的两个原因:锁定方法防止修改和提高执行效率。 ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • 树莓派Linux基础(一):查看文件系统的命令行操作
    本文介绍了在树莓派上通过SSH服务使用命令行查看文件系统的操作,包括cd命令用于变更目录、pwd命令用于显示当前目录位置、ls命令用于显示文件和目录列表。详细讲解了这些命令的使用方法和注意事项。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 测绘程序设计Excel度分秒转换模板附代码超实用版
    本文介绍了测绘程序设计Excel度分秒转换模板附代码超实用版的相关知识,包括准备工作、编写表达式和注意事项。在实际工作中,将GPS实测的经纬度度转换为度分秒是常见需求,本文提供了在Excel中快速进行转换的方法,以提高工作效率。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
author-avatar
凡秘能
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有