今天来说一波自己对Java中抽象类和接口的理解,含参考内容:

一、抽象类

1、定义:

public abstract class 类名{}

Java语言中所有的对象都是用类来进行描述,但是并不是所有的类都是用来描述对象的。我所理解的抽象类其实就是对同一类事物公共部分的高度提取,这个公共部分包括属性和行为。比如牛、羊、猪它们的公共属性是都有毛,公共行为是都哺乳,所以我们可以把公共部分抽象成一个哺乳类,含有属性毛和行为哺乳,当牛、羊、猪继承了哺乳类后也就有了哺乳的功能,至于怎么完成这个功能就需要自己去实现了。

2、特点

(1)被Abstract关键字修饰的类是抽象类;

(2)含有抽象方法的类一定是抽象类,但是抽象类不一定含有抽象方法;且抽象方法必须是public或protected,否则不能被子类继承。默认为public。

(3)抽象方法中不能有实现,否则编译报错;

(4)抽象类中可以定义自己的成员变量和成员方法;

(5)子类继承抽象类时,必须实现抽象类中的所有抽象方法,否则该子类也要被定义为抽象类;

(6)抽象类不能被实例化。

3、验证以上规定是否确实如其所述

这是我在word中编辑的一张验证表,把它截成图片放在这里:

从上图的验证结果来看,那些理论都是正确的

二、接口

1、定义:

public interface 接口名{}

接口是用来提供方法的。按我的理解,它是对多个类公共行为的高度提取,比如所有的动物它们的公共行为是吃和睡,那么我们就可以将这两个行为提取出来封装在一个接口中,当某个动物需要执行这个行为的时候只要调用该接口,然后在自己的类里面完成具体实现就行。这样理解好像跟抽象类没什么区别,那再看下面的这个例子。如果把这两个行为放在抽象类中,但是该抽象类中还有一个爬的行为,此时当一种爬行动物,比如蛇,当它继承这个类的时候,会实现吃、睡、爬行这三个方法,于是它便有了吃、睡、爬的功能;但是如果一个飞行类的动物如鸟,当它继承了这个方法的时候,同样的也有了吃、睡、爬的功能,很明显,爬不是它需要的功能,这就有点词不达意了,但是当他们继承了只有吃、睡的接口,就有了吃、睡的基本功能,至于爬和飞,可以抽象出来放在抽象类中,按需继承,按需实现自己需要的功能就OK了。

2、特点:

(1)接口中可以有自己的成员变量,但会被隐式地指定为public staic final,而且也只能是public staic final的,接口中所有的方法都是抽象方法,都会被隐式地指定为public abstract的。

(2)接口中只定义抽象方法,没有具体的实现;

(3)实现接口的类必须实现接口中定义的所有方法;

3、验证以上理论是否正确

同样,验证出上面的理论都是对的!

三、抽象类和接口的区别:

1、抽象类中可以有自己的成员方法及它们的具体实现;接口中只能含有抽象方法;

2、抽象类中可以含有各种类型的成员变量;接口中的成员变量只能是public static final的;

3、一个类只能继承一个抽象类,但可以实现多个接口;

4、抽象类中可以含有静态代码块和静态方法;接口中不能定义静态代码块和静态方法;

验证一个类只能继承一个抽象类,但能实现多个接口

首先,定义两个抽象类:一个Mummals哺乳类,一个Crawler爬行类

/**
* @createtime 2017年3月17日 上午10:33:27
* @description 哺乳类
*/
public abstract class Mammals {
public String foods; public abstract void nurse(); public void eat(String food){
this.foods = food;
System.out.println("吃"+foods);
}
}
/**
*
* @createtime 2017年3月17日 上午11:23:09
* @description 定义一个抽象类--爬行类
*/
public abstract class Crawler { public abstract void crawl();
}

其次,定义两个接口:一个是BaseAction基础接口;一个是SpecialAction特殊接口

/**
*
* @createtime 2017年3月17日 上午11:03:42
* @description 定义一个名为基本行为的接口
*/
public interface BaseAction { public String name = ""; public void eat(); public void sleep();
}
/**
* @createtime 2017年3月17日 上午11:24:56
* @description 定义一个接口用来实现特殊行为
*/
public interface SpecialAction { public void study();
}

然后,定义一个基础类People,继承Mummals类,实现BaseAction接口和SpecialAction接口

 /**
* @createtime 2017年3月17日 上午11:25:48
* @description 定义一个普通的类--人类,继承哺乳类,实现基础接口和特殊接口
*/
public class People extends Mammals implements BaseAction,SpecialAction{ @Override
public void study() {
// TODO Auto-generated method stub } @Override
public void eat() {
// TODO Auto-generated method stub } @Override
public void sleep() {
// TODO Auto-generated method stub } @Override
public void nurse() {
// TODO Auto-generated method stub } }

可以看出,一个子类是可以实现多个接口的

最后,让基础类People,同时继承Mummals类和Crawler类

/**
* @createtime 2017年3月17日 上午11:25:48
* @description 定义一个普通的类--人类,继承哺乳类,实现基础接口和特殊接口
*/
public class People extends Mammals,Crawler{
@Override
public void nurse() {
// TODO Auto-generated method stub } }

可以看到报的错惨不忍睹:

其实这个问题很显然,人类是哺乳动物而不是爬行动物,如果一个子类能够同时继承多个类,说明该子类属于多种类型,就像人既是哺乳动物,又是爬行动物,明显违背自然规律,所以一个子类只能继承一个抽象类。但是人既有所有动物哺乳动物都有的吃和睡等基础行为之外,还有着自己特殊的思考行为,所以公共的行为通过实现公共接口完成,而特殊的行为通过实现特殊接口来完成,这样就不矛盾了。(以上纯属个人观点,如有问题,望您能给你指正,谢谢了~)

四、举例

下面我以JFinal这个框架为例,来说说大神们是怎样使用抽象类和方法的,借鉴别人才能提高自己。

1、抽象类

JFinal中,我觉得最重要的抽象类应该是Controller了。

Controller是业务逻辑实现的关键抽象类,是MVC模式的控制中心,就像人的大脑。所有的类要想完成请求-响应的整个过程,都必须依赖这个类,看下面部分代码:

Controller类中既有成员变量也有成员方法,成员变量是我们写代码时,几乎所有的自定义控制类都要使用的http请求、响应相关的一些对象,如HttpServletReqquest、HttpServletResponse等,而成员方法又为我们提供了获取这些对象的行为,除此之外,还有很多实用的方法,如获取前端请求参数、返回响应结果、上传文件、验证等大量的方法,但是这个抽象类中,作者(詹波)并没有写抽象方法,可能有人会问,如果没有抽象方法,何不把它定义成普通类来继承?其实刚开始我也是这样想的,但是仔细想了一下,作者可能是想利用抽象类不能被实例化的这个功能,于是问题又出来了,为什么不让该类被实例化呢?

经过调研,我看到这样一篇文章,讲的是JDK中抽象方法不含抽象类的例子:

http://blog.csdn.net/fancylovejava/article/details/24804541,文章中说之所以它所提到的抽象类没有抽象方法,是因为里面所有的成员方法都是通过构造函数来进行传值,对于这样一个类,我们实例化它是没有意义的。于是按此逻辑看了一下Controller类,发现里面的方法基本上也都是通过构造函数来传参的,可以印证它这种说法,但是再仔细想一想,我们为什么要实例化一个类呢?不就是为了创建一个具体的对象吗。记得前面讲类是说过这么一句话,“Java中所有的对象都是通过类来描述,但并不是所有的类都是用来描述对象的”,我觉得用这句话来解释Controller是不含抽象方法的抽象类再合适不过。

首先,这个类并不是为了描述某个具体的对象而创建,它的作用是提取出所有能够被实例化的类的公共部分,这样可以减少代码量;

其次,它没有抽象方法,所有的成员方法都有实现,而这些实现也是解决了所有处理业务逻辑的类会用到的操作方法。没有抽象类,是因为没有合适的公共行为为所有业务类所有。

2、接口

Jfinal中的主要接口是插件接口IPlugin

它的源码如下:

package com.jfinal.plugin;

/**
* IPlugin
*/
public interface IPlugin {
boolean start();
boolean stop();
}

这里面只有两个抽象方法,start()和stop()

而实现它的类有很多,主要是ActiveRecordPlugin和C3pPlugin这两个,它们分别是数据库访问插件和数据库连接池插件,很明显,这两个类在实现IPlugin接口的时候,都实现了start()方法和stop()方法,start()用来启动插件,stop()用来停用插件,在C3p0Plugin中启用插件,开始连接数据库;在ActiveRecordPlugin中启动插件,开始访问数据库;源代码如下:

C3p0Plugin:

 public boolean start() {
if (isStarted)
return true; dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl(jdbcUrl);
dataSource.setUser(user);
dataSource.setPassword(password);
try {dataSource.setDriverClass(driverClass);}
catch (PropertyVetoException e) {dataSource = null; System.err.println("C3p0Plugin start error"); throw new RuntimeException(e);}
dataSource.setMaxPoolSize(maxPoolSize);
dataSource.setMinPoolSize(minPoolSize);
dataSource.setInitialPoolSize(initialPoolSize);
dataSource.setMaxIdleTime(maxIdleTime);
dataSource.setAcquireIncrement(acquireIncrement); isStarted = true;
return true;
}

ActiveRecordPlugin:

 public boolean start() {
if (isStarted) {
return true;
}
if (configName == null) {
configName = DbKit.MAIN_CONFIG_NAME;
}
if (dataSource == null && dataSourceProvider != null) {
dataSource = dataSourceProvider.getDataSource();
}
if (dataSource == null) {
throw new RuntimeException("ActiveRecord start error: ActiveRecordPlugin need DataSource or DataSourceProvider");
}
if (config == null) {
config = new Config(configName, dataSource);
} if (dialect != null) {
config.dialect = dialect;
}
if (showSql != null) {
config.showSql = showSql;
}
if (devMode != null) {
config.devMode = devMode;
}
if (transactionLevel != null) {
config.transactionLevel = transactionLevel;
}
if (containerFactory != null) {
config.containerFactory = containerFactory;
}
if (cache != null) {
config.cache = cache;
} new TableBuilder().build(tableList, config);
DbKit.addConfig(config);
Db.init();
isStarted = true;
return true;
}

以上就是自己对Java中的抽象类和接口的理解和认识,突然认识到这些用法都比较适合写框架时使用,平时做开发很少用到,或者说我没用到过,看来高级的东西还是要靠基础理论啊!

下面附上本次调研有用的一些文章链接:

1、Java接口和抽象类的区别:http://www.cnblogs.com/NewDolphin/p/5397297.html

2、抽象类没有抽象方法的例子:http://blog.csdn.net/fancylovejava/article/details/24804541

3、Java实例化对象的过程:http://www.cnblogs.com/funfei/p/5679357.html

Java问题解读系列之基础相关---抽象类和接口的更多相关文章

  1. Java问题解读系列之基础相关---含继承时的执行顺序

    今天来研究一下含继承.静态成员.非静态成员时Java程序的执行顺序: 一.不含继承,含有静态变量.静态代码块 创建一个子类,该类包含静态变量.静态代码块.静态方法.构造方法 /** * @create ...

  2. Java问题解读系列之String相关---String类为什么是final的?

    今天看到一篇名为<Java开发岗位面试题归类汇总>的博客,戳进去看了一下题目,觉得有必要夯实一下基本功了,所以打算边学边以博客的形式归纳总结,每天一道题, 并将该计划称为java问题解读系 ...

  3. Java问题解读系列之IO相关---Java深拷贝和浅拷贝

    前几天和棒棒童鞋讨论Java(TA学的是C++)的时候,他提到一个浅拷贝和深拷贝的问题,当时的我一脸懵圈,感觉自己学Java居然不知道这个知识点,于是今天研究了一番Java中的浅拷贝和深拷贝,下面来做 ...

  4. Java问题解读系列之String相关---String、StringBuffer、StringBuilder的区别

    今天的题目是String.StringBuffer和StringBuilder的区别: 首先还是去官方的API看看对这三种类型的介绍吧,Go...... 一.继承类和实现接口情况 1.String类 ...

  5. Java问题解读系列之String相关---String类的常用方法?

    今天的题目是:String类的常用方法? 首先,我们在eclipse中定义一个字符串,然后使用alt+/就会出现String类的所有方法,如下图所示: 下面我就挑选一些常用的方法进行介绍: 首先定义两 ...

  6. Java基础之抽象类与接口

    Java基础之抽象类与接口 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的时候 ...

  7. 关于Java中的对象、类、抽象类、接口、继承之间的联系

    关于Java中的对象.类.抽象类.接口.继承之间的联系: 导读: 寒假学习JavaSE基础,其中的概念属实比较多,关联性也比较大,再次将相关的知识点复习一些,并理顺其中的关系. 正文: 举个例子:如果 ...

  8. “全栈2019”Java第六十六章:抽象类与接口详细对比

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. 程序猿的日常——Java基础之抽象类与接口、枚举、泛型

    再次回顾这些基础内容,发现自己理解的又多了一点.对于一些之前很模糊的概念,渐渐的清晰起来. 抽象类与接口 抽象类通常是描述一些对象的通用方法和属性,并且默认实现一些功能,它不能被实例化.接口仅仅是描述 ...

随机推荐

  1. 【2011集训贾志鹏】Crash 的数字表格

    题面 题目分析 (默认\(n<m\)) 题目要求\(\sum\limits_{i=1}^n\sum\limits_{j=1}^mlcm(i,j)\). 由\(lcm(i,j)=\frac{i\c ...

  2. 查看java资源的占用

    1,使用命令top -p <pid> ,显示你的java进程的内存情况,pid是你的java进程号,比如1232,按H,获取每个线程的内存情况3,找到内存和cpu占用最高的线程pid,比如 ...

  3. 2016.10.7初中部上午NOIP普及组比赛总结

    2016.10.7初中部上午NOIP普及组比赛总结 这次的题还可以,重新入了比赛的前十. 进度: 比赛:90+10+70+30=200 改题:AC+AC+AC+AC=AK 找试场 这题很简单,但是被欺 ...

  4. type 命令

    type 显示属于那种类型

  5. <input> type 属性

    单行文本域 语法格式:<input  type = “text” 属性 = “值” /> 常用属性 1  name:文本框的名字.命名规则是:可以包含字母.数字.下划线,只能以字母开头. ...

  6. 6大主流开源SQL引擎总结,遥遥领先的是谁?

    根据 O’Reilly 2016年数据科学薪资调查显示,SQL 是数据科学领域使用最广泛的语言.大部分项目都需要一些SQL 操作,甚至有一些只需要SQL.本文就带你来了解这些主流的开源SQL引擎!背景 ...

  7. python格式化输出%,while else

    一.格式化输出% 需求:自我介绍模板 #格式化输出 # % s d %占位符,占个位置 s(字符串),d(数字)替换内容的类型 name = input('请输入姓名:') age = input(' ...

  8. sql里面插入语句insert后面的values关键字可省略

    插入到表名(列值)后跟一个查询语句的话就代表值,简单的说就是后面select select出来的值就是要插入的值,即  insert into tb(字段名一,字段名二)select 字段名一,字段名 ...

  9. 数据库连接客户端 dbeaver 程序包以及使用说明

    dbeaver 是一个基于 Eclipse 的数据库客户端,支持几乎所有常见的数据库.分为商业版和社区版,社区版可以免费使用. 官网和 GitHub https://dbeaver.io/ https ...

  10. NoSQL 列族数据库