[转]【原文】 

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. 【BZOJ4621】Tc605 DP

    [BZOJ4621]Tc605 Description 最初你有一个长度为 N 的数字序列 A.为了方便起见,序列 A 是一个排列. 你可以操作最多 K 次.每一次操作你可以先选定一个 A 的一个子串 ...

  2. 【BZOJ4641】基因改造 KMP

    [BZOJ4641]基因改造 Description "人类智慧的冰峰,只有萌萌哒的我寂寞地守望." --TB TB正走在改造人类智慧基因的路上.TB发现人类智慧基因一点也不萌萌哒 ...

  3. jQuery 对象访问 index([selector|element])

    搜索匹配的元素,并返回相应元素的索引值,从0开始计数. 如果不给 .index() 方法传递参数,那么返回值就是这个jQuery对象集合中第一个元素相对于其同辈元素的位置. 如果参数是一组DOM元素或 ...

  4. PHP 神奇的sprintf函数

    sprintf 1.定义 sprintf() 函数将字符串进行各种类型的格式化. 2.语法 sprintf(format,arg1,arg2,arg++) format:格式类型. arg1,arg2 ...

  5. You must reset your password using ALTER USER

    mac mysql error You must reset your password using ALTER USER statement before executing this statem ...

  6. tpot从elastic search拉攻击数据之一 找本地数据端口

    前面,我们已经在ubuntu服务器上部署好了tpot,并启动进行数据捕获 可以通过64297端口登陆到kibana可视化平台查看捕获到攻击的情况. 现在要拉取攻击数据了,但是该怎么拉呢? 看了一上午的 ...

  7. mac本配置python环境

    mac本上一般是自带python解释器的. 我选择了SublimeText2作为编辑器.安装个SublimeCodeIntel插件,可以进行代码自动补全. 新建一个python文件:hello.py ...

  8. java 遍历map的方法

    package com.jackey.topic; import java.util.ArrayList;import java.util.HashMap;import java.util.Itera ...

  9. HDU1838:Chessboard(线性dp)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1838 这题也挺不错的.首先题目说了,棋盘的右下角一定是'1',另外棋盘里面至少包含一个1,所以最小值是1, ...

  10. python-绘图matplotlib

    <Python编程:从入门到实践>读书笔记 1.使用plot()绘制简单的折线图 import matplotlib.pyplot as plt va=[1,2,3,4,5] sq=[1, ...