java父类调用被子类重写的方法
2017-07-03 14:33
387 查看
[转]【原文】 1.如果父类构造器调用了被子类重写的方法,且通过子类构造函数创建子类对象,调用了这个父类构造器(无论显示还是隐式),就会导致父类在构造时实际上调用的是子类覆盖的方法(你需要了解java继承中的初始化机制)。
例子:[java] view plain copypublic abstract class Father {
public Father() {
display();
}
public void display() {
System.out.println("Father's display");
}
}
[java] view plain copypublic class Son extends Father {
public Son() {
}
public void display() {
System.out.println("Son's display");
}
public static void main(String[] args) {
new Son();
}
}
输出为:Son's display这种机制有优点,不过有时也存在问题。优点:通过继承相同的父类,初始化子类时,父类会调用不同子类的不同复写方法,从而实现多态性。举一个Spring中的例子:Spring中可以通过为每个DAO注入一个已经用DataSource初始化的JdbcTemplate,来执行SQL语句。但是每个DAO都通过编码实现这个注入就产生了大量代码冗余,于是Spring提供了一个JdbcDaoSupport类,DAO只需继承这个类,就会自动注入已初始化好的JdbcTemplate,那么是如何做到的呢?查看源码:JdbcDaoSupport继承了DaoSupport:[java] view plain copypublic abstract class JdbcDaoSupport extends DaoSupport
DaoSupport实现了InitializingBean接口,该接口只有一个void afterPropertiesSet() throws Exception;方法,Spring会在初始化Bean的属相后查看这个Bean是否实现了InitializingBean接口,如果继承了就会自动调用afterPropertiesSet方法。那么看一下DaoSupport中的afterPropertiesSet是如何实现的:[java] view plain copypublic 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);
}
}
他这里调用了checkDaoConfig方法,此方法是抽象方法,真正运行时会去调用子类重写过的该方法。查看JdbcDaoSupport如何重写checkDaoConfig():[java] view plain copy@Override
protected void checkDaoConfig() {
if (this.jdbcTemplate == null) {
throw new IllegalArgumentException("'dataSource' or 'jdbcTemplate' is required");
}
}
JdbcDaoSupport会检查jdbcTemplate是否注入,没注入会抛出异常!这就完成了注入检测,通过子类实现具体检测的过程!这也就是当你的DAO继承了JdbcDaoSupport,但是在XML配置DAO时没有配置DataSource属性会抛出异常的原因。那么JdbcTemplate是何时注入的呢?观察JdbcDaoSupport源码,发现setDataSource()方法,框架根据XML配置初始化DAO时,会调用属性的set方法注入,如果DAO没有该set方法,则调用父类的。也就是调用JdbcDaoSupport的setDataSource方法,此时便创建了DAO执行SQL语句需要的jdbcTemplate。[java] view plain copy/**
* Set the JDBC DataSource to be used by this DAO.
*/
public final void setDataSource(DataSource dataSource) {
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
this.jdbcTemplate = createJdbcTemplate(dataSource);
initTemplateConfig();
}
}
缺点:如果在父类构造函数中调用被子类重写的方法,会导致子类重写的方法在子类构造器的所有代码之前执行,从而导致子类重写的方法访问不到子类实例变量的值,因为此时这些变量还没有被初始化。
例子:[java] view plain copypublic abstract class Father {
public Father() {
display();
}
public void display() {
System.out.println("Father's display");
}
}
[java] view plain copypublic class Son extends Father {
public Son() {
}
public void display() {
System.out.println("Son's display");
}
public static void main(String[] args) {
new Son();
}
}
输出为:Son's display这种机制有优点,不过有时也存在问题。优点:通过继承相同的父类,初始化子类时,父类会调用不同子类的不同复写方法,从而实现多态性。举一个Spring中的例子:Spring中可以通过为每个DAO注入一个已经用DataSource初始化的JdbcTemplate,来执行SQL语句。但是每个DAO都通过编码实现这个注入就产生了大量代码冗余,于是Spring提供了一个JdbcDaoSupport类,DAO只需继承这个类,就会自动注入已初始化好的JdbcTemplate,那么是如何做到的呢?查看源码:JdbcDaoSupport继承了DaoSupport:[java] view plain copypublic abstract class JdbcDaoSupport extends DaoSupport
DaoSupport实现了InitializingBean接口,该接口只有一个void afterPropertiesSet() throws Exception;方法,Spring会在初始化Bean的属相后查看这个Bean是否实现了InitializingBean接口,如果继承了就会自动调用afterPropertiesSet方法。那么看一下DaoSupport中的afterPropertiesSet是如何实现的:[java] view plain copypublic 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);
}
}
他这里调用了checkDaoConfig方法,此方法是抽象方法,真正运行时会去调用子类重写过的该方法。查看JdbcDaoSupport如何重写checkDaoConfig():[java] view plain copy@Override
protected void checkDaoConfig() {
if (this.jdbcTemplate == null) {
throw new IllegalArgumentException("'dataSource' or 'jdbcTemplate' is required");
}
}
JdbcDaoSupport会检查jdbcTemplate是否注入,没注入会抛出异常!这就完成了注入检测,通过子类实现具体检测的过程!这也就是当你的DAO继承了JdbcDaoSupport,但是在XML配置DAO时没有配置DataSource属性会抛出异常的原因。那么JdbcTemplate是何时注入的呢?观察JdbcDaoSupport源码,发现setDataSource()方法,框架根据XML配置初始化DAO时,会调用属性的set方法注入,如果DAO没有该set方法,则调用父类的。也就是调用JdbcDaoSupport的setDataSource方法,此时便创建了DAO执行SQL语句需要的jdbcTemplate。[java] view plain copy/**
* Set the JDBC DataSource to be used by this DAO.
*/
public final void setDataSource(DataSource dataSource) {
if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {
this.jdbcTemplate = createJdbcTemplate(dataSource);
initTemplateConfig();
}
}
缺点:如果在父类构造函数中调用被子类重写的方法,会导致子类重写的方法在子类构造器的所有代码之前执行,从而导致子类重写的方法访问不到子类实例变量的值,因为此时这些变量还没有被初始化。
相关文章推荐
- Java父类调用被子类重写的方法
- java父类调用被子类重写的方法
- JAVA笔试题总结3:父类构造器调用被子类重写方法
- Java的重写与调用父类方法问题
- Java方法重写到底调用哪儿一个方法,到底用本类还是父类的成员变量
- Java父类对象调用子类实体:方法重写与动态调用
- java 通过子类怎么调用父类已经被重写的方法
- java调用祖父类里被父类重写了的实例方法
- java里重写某个方法后为什么在重写的方法里还要调用父类的该方法?
- Java中不要在父类的构造方法中调用会被子类重写的方法
- JAVA_继承演示03_ExtendsDeamo01.java super关键字 重写父类的方法,中,调用父类的方法
- Java父类对象调用子类实体:方法重写与动态调用
- Java 子类未重写的方法调用父类还是子类的问题
- 重写父类方法、super关键字、调用父类构造器——Java
- java方法重写的时候,一个调用父类还是子类方法的问题
- Java__子类中调用父类重写的方法。
- Java的重写与调用父类方法问题
- JAVA_继承演示03_ExtendsDeamo01.java super关键字 重写父类的方法,中,调用父类的方法
- 在java中父类调用子类中的方法
- 异常父类为什么java中子类重写父类的方法时声明抛出异常不能比父类范围大