java父类调用被子类重写的方法

Posted 小小鸟儿!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java父类调用被子类重写的方法相关的知识,希望对你有一定的参考价值。

[转]【原文】 

1.如果父类构造器调用了被子类重写的方法,且通过子类构造函数创建子类对象,调用了这个父类构造器(无论显示还是隐式),就会导致父类在构造时实际上调用的是子类覆盖的方法(你需要了解java继承中的初始化机制)。

例子:
[java] view plain copy
  1. public abstract class Father {  
  2.     public Father() {  
  3.         display();  
  4.     }  
  5.   
  6.     public void display() {  
  7.         System.out.println("Father‘s display");  
  8.     }     
  9. }  
[java] view plain copy
  1. public class Son extends Father {  
  2.   
  3.     public Son() {  
  4.     }  
  5.   
  6.     public void display() {  
  7.         System.out.println("Son‘s display");  
  8.     }  
  9.       
  10.     public static void main(String[] args) {  
  11.         new Son();  
  12.     }  
  13.   
  14. }  


技术分享
输出为:
Son‘s display
技术分享
这种机制有优点,不过有时也存在问题。

优点:通过继承相同的父类,初始化子类时,父类会调用不同子类的不同复写方法,从而实现多态性。
举一个Spring中的例子:
Spring中可以通过为每个DAO注入一个已经用DataSource初始化的JdbcTemplate,来执行SQL语句。但是每个DAO都通过编码实现这个注入就产生了大量代码冗余,于是Spring提供了一个JdbcDaoSupport类,DAO只需继承这个类,就会自动注入已初始化好的JdbcTemplate,那么是如何做到的呢?查看源码:
JdbcDaoSupport继承了DaoSupport:
技术分享
[java] view plain copy
  1. public abstract class JdbcDaoSupport extends DaoSupport  
DaoSupport实现了InitializingBean接口,该接口只有一个void afterPropertiesSet() throws Exception;
方法,Spring会在初始化Bean的属相后查看这个Bean是否实现了InitializingBean接口,如果继承了就会自动调用afterPropertiesSet方法。
技术分享
那么看一下DaoSupport中的afterPropertiesSet是如何实现的:
[java] view plain copy
  1. public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {  
  2.         // Let abstract subclasses check their configuration.  
  3.         checkDaoConfig();  
  4.   
  5.         // Let concrete implementations initialize themselves.  
  6.         try {  
  7.             initDao();  
  8.         }  
  9.         catch (Exception ex) {  
  10.             throw new BeanInitializationException("Initialization of DAO failed", ex);  
  11.         }  
  12.     }  
他这里调用了checkDaoConfig方法,此方法是抽象方法,真正运行时会去调用子类重写过的该方法。
查看JdbcDaoSupport如何重写checkDaoConfig():
[java] view plain copy
  1. @Override  
  2.     protected void checkDaoConfig() {  
  3.         if (this.jdbcTemplate == null) {  
  4.             throw new IllegalArgumentException("‘dataSource‘ or ‘jdbcTemplate‘ is required");  
  5.         }  
  6.     }  

技术分享JdbcDaoSupport会检查jdbcTemplate是否注入,没注入会抛出异常!这就完成了注入检测,通过子类实现具体检测的过程!这也就是当你的DAO继承了JdbcDaoSupport,但是在XML配置DAO时没有配置DataSource属性会抛出异常的原因。
那么JdbcTemplate是何时注入的呢?观察JdbcDaoSupport源码,发现setDataSource()方法,框架根据XML配置初始化DAO时,会调用属性的set方法注入,如果DAO没有该set方法,则调用父类的。也就是调用JdbcDaoSupport的setDataSource方法,此时便创建了DAO执行SQL语句需要的jdbcTemplate。
[java] view plain copy
  1. /** 
  2.      * Set the JDBC DataSource to be used by this DAO. 
  3.      */  
  4.     public final void setDataSource(DataSource dataSource) {  
  5.         if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) {  
  6.             this.jdbcTemplate = createJdbcTemplate(dataSource);  
  7.             initTemplateConfig();  
  8.         }  
  9.     }  


缺点:如果在父类构造函数中调用被子类重写的方法,会导致子类重写的方法在子类构造器的所有代码之前执行,从而导致子类重写的方法访问不到子类实例变量的值,因为此时这些变量还没有被初始化。






以上是关于java父类调用被子类重写的方法的主要内容,如果未能解决你的问题,请参考以下文章

java子类重写父类带泛型的方法

Java 的 JPanel 子类中重写父类的 paint 方法 会被自动调用,请问调用的条件或时机

php子类能不能重写父类的private方法?

Java中子类重写父类的方法为啥返回值类型要小于等于父类方法的返回值类型?

Object在其子类中,为啥不能调用clone()???

java中,子类能调用父类中所有方法、对象吗?是不是父类也能调用子类所有……?