`

[#0x000B] warning: 在构造器中请谨慎使用被覆写方法

    博客分类:
  • Java
阅读更多

  先上代码(adapted from Chapter 8, Thinking in Java, Fourth Edition):

class Glyph
{
	void draw() 
	{ 
		System.out.println("Glyph.draw()");
	}
	
	Glyph()
	{
		System.out.println("Glyph constructor");
		draw();
	}
}	

class RoundGlyph extends Glyph 
{
	private int radius = 1;

	RoundGlyph(int r)
	{
		System.out.println("before assignment in constructor, radius = " + radius);
		radius = r;
		System.out.println("RoundGlyph constructor, radius = " + radius);
	}
	
	void draw()
	{
		System.out.println("RoundGlyph.draw(), radius = " + radius);
	}
}	

public class PolyConstructors
{
	public static void main(String[] args)
	{
		new RoundGlyph(5);
	}
}
//Output:
/*
	Glyph constructor
	RoundGlyph.draw(), radius = 0
	before assignment in constructor, radius = 1
	RoundGlyph constructor, radius = 5
*/

  根据[#0x0008],调用RoundGlyph的构造器时,会先调用Glyph的构造器。Glyph的构造器里调用了一个被覆写方法draw()。这里我们惊奇地发现:虽然RoundGlyph对象还没有创建完毕,但Glyph的构造器却实际调用了RoundGlyph的draw()方法(覆写方法),而且radius == 0(参JVM-Spec $2.17.6 Creation of New Class Instances 最后一段

If methods are invoked that are overridden in subclasses in the object being initialized, then these overriding methods are used, even before the new object is completely created.)。

  由此,我们可以对[#0x0008]做一些补充,即在调用ext class的constructor时,会有如下的过程:

  ->将分配给该ext class object的内存空间全部初始化为0x00(即用0x00填满该段内存空间);

  ->调用base class的constructor。如果base class的constructor有使用被覆写方法的话,则实际调用ext class中的覆写方法。由于上一个步骤的原因,此时ext class中各field均为0;

  ->base class的constructor调用完毕后后,开始初始化(包括默认初始化)ext class的member;

  ->调用ext class的constructor。

 

(2009年09月04日归纳:[#0x0023])

分享到:
评论

相关推荐

    行业分类-设备装置-一种数据覆写方法.zip

    在IT行业中,数据覆写是一种常见的数据安全处理技术,尤其在设备装置的管理与保护中扮演着重要角色。本文将详细解析标题“行业分类-设备装置-一种数据覆写方法”所涉及的知识点,以及从描述中我们可以推测的关于数据...

    Java 编程军规.docx

    例如,直接在代码中使用数字`1`表示成功状态,而不加以注释或定义为常量。这样不仅降低代码的可读性,也不利于日后的维护与修改。 - **实践建议**:对于特定的数值,应当定义为具有明确含义的常量。例如,定义`...

    重载与覆写/重写的区别

    可是对于覆写而言,绝对不能修改返回值类型,但是在子类中所覆写的方法应该可以继续进行重载。 重载(Overloading)  (1) 方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时...

    你必须知道的.net

    这些转换在.NET中自动发生,但在性能密集型应用中,应谨慎使用,以避免不必要的性能开销。 #### 深入理解关键字:new、base、this等 - **new关键字**:在.NET中,new关键字具有多重用途,不仅可以用于实例化新对象...

    Effective_C#_中文版改善C#程序的50种方法

    接口实现与虚函数重载的区别在于,接口用于实现多态,而虚函数重载允许在派生类中覆写基类的方法。 在设计回调和事件接口时,应使用委托和事件来定义外部接口,避免返回内部类对象的引用,这样可以减少潜在的耦合和...

    收汇宝网络技术服务有限公司面试题目

    - 在web.xml中配置Servlet或者使用注解配置。 #### 题目二:文件读取与统计 **题目描述**:读取一个名为`test.txt`的文件,并统计其中每个英文字符出现的次数。 **知识点解析**: 1. **文件操作**:使用Java中的`...

    一次JAVA面试遇到的题目

    - **局部变量的定义**:局部变量是在方法、构造器或者块中定义的变量。这些变量只在定义它们的方法或作用域内可见。 - **局部变量的修饰符**:局部变量不能使用访问控制修饰符(如 `private`、`public` 或 `...

    php实现parent调用父类的构造方法与被覆写的方法

    在子类中定义构造方法时,需要传递参数给父类的构造方法,否则我们得到的可能是一个构造不完整的对象。 要调用父类的方法,首先要找到一个引用类本身的途径:句柄(handle),PHP为此提供了parent关键字。   parent...

    C#绝对经典面试题及解答

    #### 问题六:B/S结构系统中传递变量值的方法 **题目描述**: 在B/S结构的系统中,如果需要传递变量值,但是又不能使用Session、Cookie、Application,请问有哪些方法可以处理? **解答**: 除了常用的Session、...

    jackrabbit

    **原因分析**:`DatabaseFileSystem.checkSchema()` 方法中使用 `DatabaseMetaData.getTables()` 来判断表是否已存在。然而,在 Oracle 数据库中,该方法可能无法正常工作,导致建表失败。这可能是由于登录用户的...

    解决Kotlin 类在实现多个接口,覆写多个接口中相同方法冲突的问题

    在Kotlin编程语言中,类可以实现多个接口,但当这些接口定义了相同的函数签名时,会出现覆写方法的冲突。解决这个问题的关键在于利用Kotlin的语法特性来明确指定调用哪个接口的方法。本文将详细讲解如何处理这种冲突...

    javascript 方法覆写实例代码

    在JavaScript中,方法覆写是一个常见的概念,它指的是在子类或者函数作用域中重新定义一个与父类或者外部作用域中同名的方法,以实现特定的功能。方法覆写通常用于实现多态性,即允许子类提供特定的实现。 在本例中...

    java知识点整理(良心出品必属精品).doc

    4. 不能在构造函数中同时使用`super`和`this`,且它们必须位于构造函数的第一行。 5. 父类引用指向子类对象:`父类类型 对象名 = new 子类构造函数();` #### final关键字 1. 修饰属性:初始化后不能再修改,常量。 ...

    J2ME三种低级用户界面事件处理技术比较

    1. **启用keyStates**:在GameCanvas子类的构造方法中,通过`super(true);`语句启用按键状态处理能力。 2. **获取按键状态**:通过`getKeyStates()`方法获取当前按键状态,值得注意的是,此操作会清除已按下的按键...

    LINUX操作系统手机刷机包(.SBF 文件)制作、修改方法.pdf

    2. **替换文件**:打开已修改的new_cg43.smg文件,复制其内容,回到.SBF文件中,使用“写入(从当前位置覆写)”功能替换原有的CG43.smg。 3. **更新校验值**:计算新CG43的校验值,并更新.SBF文件中的相应位置(例如...

    27.面向对象高级-继承的进一步研究

    - 如果父类中的方法被声明为`private`,那么即使子类中声明了同名方法,也不能认为这是覆写行为,因为子类无法访问到父类中的私有方法。 #### 属性的覆盖 除了方法覆写之外,还可以通过子类重新定义父类的属性来...

    架构师2015-05

    - 非标准技术方案在短期内可以快速解决问题,提高用户体验,如阿里云在应对XSA-123漏洞时采用的内存覆写技术。 - 但从长期来看,过多依赖非标准技术可能导致系统维护成本上升、技术债务累积等问题。 3. **权衡...

    Effective Java第三版1

    7. **终结方法与清理器**:Java中的`finalize`方法往往不推荐使用,因为它不能保证执行,性能影响且可能导致不可预测的行为。 8. **try-with-resources**:从Java 7开始,try-with-resources语句使得资源的自动关闭...

Global site tag (gtag.js) - Google Analytics