1.如果父类构造器调用了被子类重写的方法,且通过子类构造函数创建子类对象,调用了这个父类构造器(无论显示还是隐式),就会导致父类在构造时实际上调用的是子类覆盖的方法(你需要了解java继承中的初始化机制)。
public abstract class Father { public Father() { display(); } public void display() { System.out.println("Father's display"); } }
public 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:
public abstract class JdbcDaoSupport extends DaoSupport
DaoSupport实现了InitializingBean接口,该接口只有一个void afterPropertiesSet() throws Exception;
方法,Spring会在初始化Bean的属相后查看这个Bean是否实现了InitializingBean接口,如果继承了就会自动调用afterPropertiesSet方法。
那么看一下DaoSupport中的afterPropertiesSet是如何实现的:
public 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():
@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。
/** * 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(); } }
缺点:如果在父类构造函数中调用被子类重写的方法,会导致子类重写的方法在子类构造器的所有代码之前执行,从而导致子类重写的方法访问不到子类实例变量的值,因为此时这些变量还没有被初始化。
转:http://blog.csdn.net/zhuoaiyiran/article/details/19489745
相关推荐
Java子类调用父类的方法中包含子类重写的实例方法 Java 子类调用父类的方法中包含子类重写的实例方法是 Java 编程语言中一个重要的概念。下面我们将详细介绍这个概念,包括相关的知识点和示例代码。 子类调用父类...
4. 重写方法的访问权限不能小于被重写的方法,例如,父类的`public`方法不能被子类的`private`方法重写。 5. 重写方法在子类中可以改变父类方法的实现,但不能改变方法的签名(返回类型和参数列表)。 理解这些概念...
文章围绕子类继承父类成员的过程、成员变量及方法的赋值、重写、覆盖等问题展开讨论,旨在帮助读者更好地理解Java继承中的重点与难点。 #### 关键词 - 继承机制 - 父类 - 子类 #### 一、超类的属性或方法在继承...
* (如果是重写即子类将父类的实例方法重写类,则调用子类的,如果是隐藏即方法则父类中声明为静态方法,则调用父类本身的但具体方法中的成员是否被子类修改需要进行分析) —> * 下一层次的父类中重复前一个过程
abstract 修饰符可以使得类不能被实例化、方法必须被子类重写。 八、接口 接口是 Java 中的一种机制,允许解决多重继承的问题。接口中的方法都是抽象的,必须被实现类实现。接口可以声明属性,属性默认为 public ...
1. **final方法**:声明为`final`的方法不能被子类重写,确保行为的不可变性。 十、static关键字 1. **静态方法**:与类相关联,而不是类的实例。它们可以直接通过类名调用,无需创建对象。 在学习ACC"P5.0"的第七...
3. 此题考察的是重写方法的调用。当通过父类的引用调用子类重写的方法时,将会执行子类中定义的方法,因此输出结果是“Child.test()”。 4. 此题是关于静态方法的覆盖问题。静态方法不是动态绑定的,即不会根据对象...
由于多态性,通过父类引用调用子类对象的方法时,实际上是调用了子类的重写方法。 3. **注意事项**: - **返回类型、方法名称和参数列表必须完全匹配**:这是识别重写方法的关键。 - **访问级别**:子类重写的...
例如,被子类重写的方法不能拥有比父类方法更加严格的权限。例如,如果父类中的方法是 public 的,那么子类中的方法也不能是 private 的。 相比之下,方法重载和方法重写是不同的概念。方法重载是指在同一个类中...
此外,重写方法的访问权限不能低于被重写方法的权限,比如父类的`public`方法不能被子类的`protected`或`private`方法重写。 重写还有以下规则: 1. `final`方法不能被重写。 2. `static`方法不能被重写,但可以在...
Java 中规定,被子类重写的方法不能拥有比父类方法更加样额的访问权限。 (4). 由于父类的访问权限修饰符限制一定要大于被子类重写的方法的访问权限修饰符,而 private 权限最小,所以如果某一个方法在父类的访问...
重载与覆写/重写的区别 ... 父类中private方法不能被子类重写,因为private只有父类本类可见。 */ /** * 6. 静态方法不存在重写概念,重写是面向对象特性,静态方法是类方法,用类名直接访问。 */ 复制代码
Java 进阶 Java 是一种跨平台的编程语言,具有三大特性:封装、继承和多态。 封装 封装是 Java 的一大特性,它可以将现实世界中的事物抽象出来,具有特定的属性和方法...这些方法可以被子类重写,以实现不同的行为。
- `super`关键字则用于引用父类的对象,主要用于调用父类的成员变量或方法,尤其是当子类重写了父类的方法时,`super`可以调用父类的原版方法。在构造器中,`super()`用于调用父类的构造器。 3. **继承关系**: -...
需要注意的是,子类不能重写父类中的private方法,且如果子类重写方法的访问权限比父类方法的权限更低,会导致编译错误。父类中的静态方法若要被子类覆盖,也需要用静态方法来实现。 抽象类和接口是Java中用于实现...
- 重写方法不能降低访问权限,父类的public方法在子类中仍需保持public。 4. 构造器和`super()`关键字 - 子类构造器在创建对象时总会调用父类构造器,如果没有显式调用,会默认调用无参构造器。 - `super()`用于...
2. **父类的构造方法子类不能继承**:尽管子类可以继承父类的方法和属性,但父类的构造方法不会被子类继承。子类创建对象时需要通过`super`关键字来调用父类的构造方法。 3. **在Java中使用关键字extends实现继承**...
这些题目涵盖了Java的核心概念,如类、接口、构造器、包管理、异常处理、方法重载、对象初始化、事件处理和文件I/O。了解这些知识点对于理解Java编程至关重要。 此外,还提到了`final`关键字的用法,它不仅可以修饰...
Java抽象类是Java编程语言中的一种特殊类型的类,它们用来定义父类,提供方法和变量的定义,但不能被实例化。抽象类是使用abstract关键字修饰的类,它们不能被实例化,必须被子类继承。 抽象类的概念 抽象类是指...