[转]【原文】 

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. poj3372

    Candy Distribution Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5868   Accepted: 327 ...

  2. nodemailer发送邮件各个服务器接口

    来自:https://github.com/nodemailer/nodemailer-wellknown/blob/master/services.json#L125 {   "1und1 ...

  3. Storm的组件

    摘自网上 当时写的很好,很详细的介绍了各个组件直接的关系 Storm集群和Hadoop集群表面上看很类似.但是Hadoop上运行的是MapReduce jobs,而在Storm上运行的是拓扑(topo ...

  4. 找不到Microsoft Access Driver(*.mdb)ODBC驱动程序的安装例程。请重新安装驱动

    按照教材创建的方法:“控制面板-管理工具-数据源(ODBC)”,打开“ODBC数据源管理器”窗口,然后“添加”,打开“创建新数据源”的窗口,最后选择Microsoft Access Driver(*. ...

  5. Casperjs中fill提交表单遇到的问题

    1.if you access internet with proxy please add             --ignore-ssl-errors=true --ssl-protocol=a ...

  6. python迭代器、生成器、yield和xrange

    https://blog.csdn.net/u010138758/article/details/56291013

  7. GetWindowThreadProcessId

    函数功能:该函数返回创建指定窗口线程的标识和创建窗口的进程的标识符,后一项是可选的. 函数原型:DWORD GetWindowThreadProcessld(HWND hwnd,LPDWORD lpd ...

  8. Tomcat 服务器介绍

    Tomcat 目录介绍 Tomcat 主目录有 bin, conf, lib, logs, temp, webapps, work 7个文件夹 bin 目录 主要用来存放 tomcat 命令 .sh ...

  9. DHTML 简介

    DHTML, 动态的 html, 不是一门语言, 是多项技术综合体的简称.其中包括了 html, CSS, DOM, javascript. HTML : 负责提供标签, 对数据进行封装,目的是便于对 ...

  10. 原!mysql5.6 存储过程 批量建表

    由于业务需求,需要按天分表,因此写了个存储过程,根据时间生成表. 根据createTime 的时间,以及 while循环的变量设置范围,生成该指定日期及之后的多张表. BEGIN ); ); ; '; ...