一、抽象类
1、概念:关键词abstract声明的类叫作“抽象类”,一个类里面有1个或多个抽象方法的类就必须定义为抽象类。但是,没有抽象方法的类也可以只是用abstract修饰定义为抽象类。
2、特点:
(1)抽象类是类,具有类所有的特性,可以拥有成员变量和普通的成员方法;
(2)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
(3)可以实现接口,并且可以只实现接口中的一个方法;
(4)可以继承类,抽象类和实体类都可以;但是如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为abstract类;
(5)抽象类不能用来创建对象,不能被实例化,但是抽象类有构造方法。
代码示例:如下的代码是我们所熟悉的spring框架的底层DaoSupport类
package org.springframework.dao.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
//此处抽象类DaoSupport 实现了接口 InitializingBean 初始化Bean配置
public abstract class DaoSupport implements InitializingBean {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
//final 阻止此方法被继承
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
// Let abstract subclasses check their configuration.
checkDaoConfig();
// Let concrete implementations initialize themselves.
try {
initDao();
}
catch (Exception ex) {
throw new BeanInitializationException("Initialization of DAO failed", ex);
}
}
//abstract 抽象方法,继承此类的子类必须实现该方法
protected abstract void checkDaoConfig() throws IllegalArgumentException;
protected void initDao() throws Exception {
}
}
package org.mybatis.spring.support;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.support.DaoSupport;
import org.springframework.util.Assert;
//此SqlSessionDaoSupport 抽象类继承了DaoSupport 抽象类
public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSession sqlSession;
private boolean externalSqlSession;
@Autowired(required = false)
public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (!this.externalSqlSession) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
@Autowired(required = false)
public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSession = sqlSessionTemplate;
this.externalSqlSession = true;
}
public final SqlSession getSqlSession() {
return this.sqlSession;
}
/**
* {@inheritDoc}
*/
protected void checkDaoConfig() {
Assert.notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
}
二、接口
1、概念:使用interface来定义一个接口,可以理解为接口是一种特殊的抽象类。
2、特点:
(1)接口内所有方法只有声明,没有具体实现,没有方法体(隐式声明),方法都是抽象的,属性默认为 public abstract,例如:public abstract void func();
(2)接口内的所有变量都默认是public static final ,必须被显示初始化;
(3)接口没有构造方法,不能被实例化;
(4)实现接口的类要实现所有的抽象方法,否则该类就必须声明为抽象类,加上 abstract关键字;
(5)接口不可以实现接口(因为所有接口都是抽象方法),但是接口支持多继承。例如:public interface func extends func1, func2。
代码示例:如下的代码是我们所熟悉的spring框架的底层InitializingBean接口
package org.springframework.beans.factory;
/**
* Interface to be implemented by beans that need to react once all their
* properties have been set by a BeanFactory: for example, to perform custom
* initialization, or merely to check that all mandatory properties have been set.
*/
public interface InitializingBean {
/**
* Invoked by a BeanFactory after it has set all bean properties supplied
* (and satisfied BeanFactoryAware and ApplicationContextAware).
* <p>This method allows the bean instance to perform initialization only
* possible when all bean properties have been set and to throw an
* exception in the event of misconfiguration.
* @throws Exception in the event of misconfiguration (such
* as failure to set an essential property) or if initialization fails.
*/
//方法都是抽象的,属性默认为 public abstract
void afterPropertiesSet() throws Exception;
}
三、抽象类和接口的区别
1、抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2、抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3、接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4、一个类只能继承一个抽象类,而一个类却可以实现多个接口;
5、抽象类:展示是不是的关系,抽象类提出公共部分,让其子类继承,使继承了该抽象类的所有子类都拥有这个属性或方法,不用各个类再都写一遍那个属性和方法,精简代码,提高开发质量;譬如,一个类需要实现一个接口中的某一个方法,但是这个接口有很多的方法,这时就可以先定义一个抽象类,去实现这个接口,并只实现你所需要的这一个方法,再写一个子类,继承这个抽象方法,这样便不用实现那个接口中的所有方法了。举例:定义一个person类,给person类一些属性,用teacher类和student类去继承这个person类,老师和学生都有了人的一些共同属性;
6、接口:展示有没有的关系,定义一个接口,在接口里面声明一些方法,让实现该接口的类,具体实现这些方法;如:定义一个learn接口,并声明一个learnKnowledge()方法,用teacher类和student类去是实现这个learn接口,实现里面学习方法,学习不同的内容。
总结:在日常写代码的过程中,我们通常会写很多接口,用于解耦,对于接口的理解应该熟悉,但抽象类相对就写得较少,其实,抽象类应用得当,在代码的精简和提升上有很大帮助的;留心一下,看底层代码的时候,就会发现,抽象类应用非常多,所以对抽象类的熟练掌握应用也是很必要的。
(注:第一次写博客,知识,技术有限,难免出错,如发现问题,欢迎指正,感谢。)