[转]【原文】 

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

例子:
[java] view plain copy
  1. public abstract class Father {
  2. public Father() {
  3. display();
  4. }
  5. public void display() {
  6. System.out.println("Father's display");
  7. }
  8. }
[java] view plain copy
  1. public class Son extends Father {
  2. public Son() {
  3. }
  4. public void display() {
  5. System.out.println("Son's display");
  6. }
  7. public static void main(String[] args) {
  8. new Son();
  9. }
  10. }
输出为:
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. // Let concrete implementations initialize themselves.
  5. try {
  6. initDao();
  7. }
  8. catch (Exception ex) {
  9. throw new BeanInitializationException("Initialization of DAO failed", ex);
  10. }
  11. }
他这里调用了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父类调用被子类重写的方法的更多相关文章

  1. Java中方法的继承以及父类未被子类覆盖的方法调用的问题

    在看java继承这一块的时候发现了一个问题,即父类未被子类覆盖的方法是如何调用的? 是子类拥有了父类的该方法只是没有显示表示,还是子类调用了父类的该方法. 为此做了一下验证 代码如下: public ...

  2. Effective Java 第三版——10. 重写equals方法时遵守通用约定

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  3. java 父类引用指向子类对象---动态绑定

    知识点: 1.java 中父类引用指向子类对象时动态绑定针对的只是子类重写的成员方法: 2.父类引用指向子类对象时,子类如果重写了父类的可重写方法(非private.非 final 方法),那么这个对 ...

  4. 利用java反射调用类的的私有方法--转

    原文:http://blog.csdn.net/woshinia/article/details/11766567 1,今天和一位朋友谈到父类私有方法的调用问题,本来以为利用反射很轻松就可以实现,因为 ...

  5. java继承-子类调用父类的方法中包含子类重写的方法

    # 看题目是不是很绕,这个我也不知道怎么才能更简单的表达了... # 先看代码: public class Common { public static void main(String[] args ...

  6. java 实例化是调用了子类重写方法

    java 实例化时调用了抽象方法或者class里面某个方法,如果子类有重写改方法,实际运行的是子类重写方法 package auto.test; //抽象父类 public abstract clas ...

  7. java父类与接口有相同的方法

    这是java多态的一个体现,如果一个类classA继承了类classB,有实现了接口interfaceA,并且接口中有方法funA(),且父类classB中也有funA(),那么对于classA来说既 ...

  8. Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. java实体类如果不重写toString方法,会如何?

    先认识一下Object Object 类的 toString 方法 返回一个字符串,该字符串由类名(对象是该类的一个实例).at 标记符“@”和此对象哈希码的无符号十六进制表示组成.换句话说,该方法返 ...

随机推荐

  1. 【BZOJ2212】[Poi2011]Tree Rotations 线段树合并

    [BZOJ2212][Poi2011]Tree Rotations Description Byteasar the gardener is growing a rare tree called Ro ...

  2. 170111、MapperScannerConfigurer处理过程源码分析

    前言 本文将分析mybatis与spring整合的MapperScannerConfigurer的底层原理,之前已经分析过java中实现动态,可以使用jdk自带api和cglib第三方库生成动态代理. ...

  3. 160620、利用 jQuery UI 和 Ajax 创建可定制的 Web 界面

    如今,网站比以往更具可定制性,允许用户更改其空间,根据自己的喜好对其进行个性化.个性化的主页或仪表板页面(例如 iGoogle.MyYahoo! 和 MyAOL)日渐普及,大多数 Web 应用程序内甚 ...

  4. 160812、apache milagro分布式安全认证系统

    java32位.64位及js的代码:http://pan.baidu.com/s/1cqnwuE 一.云链接为中心的软件及需要互联网规模物联网设备 二.利用双线性密码学分发加密操作和分裂的加密参数 三 ...

  5. delphi--自带控件(Tcheckbox、TComBobox、TpageControl、TDBGrid,TScrollBox,TEdit)

    一.TCheckBox 使CheckBox选中CheckBox1.Checked := True;选择发生变化 ,OnClick事件if CheckBox1.Checked thenbegin //. ...

  6. 巨蟒python全栈开发flask9 项目开始1

    1.项目需求分析 立项:Javis&&taisen(三个月全部,先模拟出一个玩具,硬件需要周期长一些) 想法 --- 需求分析: .通过玩具与孩子实时进行沟通 .希望玩具的知识渊博 . ...

  7. php 正则表达式三.模式修正

    1.贪婪模式和懒惰模式, 贪婪模式:php中正则默认是贪婪模式,匹配尽可能多 的字符,比如 $pattern='/a+b/'; $subject='aaaaaaaaab,那么可能会preg_match ...

  8. Python SQLAlchemy基本操作和常用技巧(包含大量实例,非常好)

    https://www.jb51.net/article/49789.htm 首先说下,由于最新的 0.8 版还是开发版本,因此我使用的是 0.79 版,API 也许会有些不同.因为我是搭配 MySQ ...

  9. myeclipse部署web项目部署按钮无效

    找到MyEclipse的工作路径,我的是“E:\Java”,到这个目录中去“\.metadata\.plugins\org.eclipse.core.runtime\.settings”找一个含有de ...

  10. pandas 如何判断指定列是否(全部)为NaN(空值)

    判断某列是否有NaN df['$open'].isnull().any() # 判断open这一列列是否有 NaN 判断某列是否全部为NaN df['$open'].isnull().all() # ...