`
len-len
  • 浏览: 21951 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

java中在创建对象时候的初始化顺序(二)

    博客分类:
  • java
阅读更多

   如果对执行顺序不是很理解的童鞋,建议先看我的第一篇文章

   http://len-len.iteye.com/blog/1412463

   在上一篇《java中在创建对象时候的初始化顺序》中大致的介绍了在继承,多态等情况下,对象大致的初始化顺序。这节讲讲一些特殊的情况,特别是和构造器结合起来,在构造器中调用一些方法的时候,出现的现象。我们先看例子(内容出自《think in java》300-301页)。

    A类--父类

package extend;
public class A {
	public A(){
		draw();
	}
	public void  draw(){
		System.out.println("调用了父类的draw方法");
	}
}

    B类--子类

package extend;
public class B extends A{
	public int i = 1;
	public B(int i){
		this.i=i;
	}
	public void draw(){
		System.out.println("调用的子类的方法");
		System.out.println("i 等于:"+i);
	}
	public static void main(String[] args) {
		B b =  new B(5);
	}
}

    结果:

i 等于:0
调用的子类的方法

      怎么样!结果有些让你失望和疑惑吧,第一个疑惑为什么调用B中的draw方法,第二个为什么i=0。我看到这时,我迷糊了好久,但是后来想了想又觉得合理。

      理由呢?还是从初始化顺序说起,我们知道子类对象的创建,一定会调用父类的构造器(不一定是无参的)这是在一般构造器中没有调用其他方法的时候,如果父类构造器调用了其他的方法,也就是"绑定"(如果对绑定不熟悉或是不清楚可以看我的另外一个文章《final讲解》)了其他方法的时候会出现什么问题呢,大家看到了结果,发现调用了子类的方法。为什么会这样呢???

      问题的根源是绑定,到底绑定的哪个方法,A中draw还是B中draw,这个是由创建的对象决定的,也就是说你创建的是B对象,那么是由B对象决定的,但是有人会说,你这个例子A中的draw方法被覆盖,可以说是B对象决定的,但是如果A中有其他的方法,而B没有覆盖,那么肯定会调用A中的方法,怎么说是B决定的呢?这种说法也没错,但是我的也没错,为什么?因为B继承了A,那么B继承了A的所有的可以继承的方法,所以这个方法也可以认为是B的。

      第一个疑惑解决了,第二个呢?为什么i为0,不是B中已经初始化了么,不是说属性在构造器之前就初始化了么?这个要说说初始化另外一个问题,我们知道属性不给它赋值也不会报错,不是0,null,就是false嘛,对,确实是这样的,这样一个初始化的过程是在一切事物之前就完成的,也就是说,在什么都没有发生前面,这些属性就赋予默认值了。下一步按照上篇文章讲到的,调用基类的构造器了,基类构造器中的draw方法是B中的方法,而B此时i还是0,所以结果就是那样。

     讲到这里,相信大家明白了。 总结几句话,第一句:在多态的情况下,创建的对象决定了调用的方法。第二句:给对象赋予默认值会在其他任何情况发生前。第三句:不要有事没事在构造器中绑定其他方法

 

4
2
分享到:
评论
8 楼 len-len 2012-02-29  
7楼说的不错,如果换成static,根据第一篇文章讲述的,静态对象总是在第一次使用类的静态对象和创建对象的时候调用。并且是在其他非静态对象和构造器之前初始化的,所以当调用父类的构造器的时候,i已经初始化完毕,不在是,默认值,所以不会是0。
7 楼 lvjun106 2012-02-28  
呵呵。试试把i换成static类型试试。
所以还要特别注意类初化时,类中的static变量。它是首次加载的。
6 楼 flyfy1 2012-02-28  
呵呵,囧了~~是啊我忘记写Extend了⋯⋯:)
5 楼 len-len 2012-02-28  
flyfy1 写道
奇怪⋯⋯你用的是什么版本的Java啊?我刚刚实验了一下,没有这个问题啊~?
附上Code:
class A {
	public A(){
		draw();
	}
	public void  draw(){
		System.out.println("Father's method");
	}
}

public class TExtend {
	public int i = 1;  
    public TExtend(int i){  
        this.i=i;  
    }  
    public void draw(){  
        System.out.println("Son's method");
        System.out.println("i = " + i);  
    }  
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("In Main");
		TExtend te = new TExtend(5);
	}

}




貌似你的 TExtend 没有继承A,你试试继承了之后的效果,谢谢你的评论哦
4 楼 flyfy1 2012-02-28  
output是:

In Main
就没了。
说明没有Call到draw method的。

如果在B的constructor里面call draw method,那么output:

In Main
Son's method
i = 1
3 楼 flyfy1 2012-02-28  
奇怪⋯⋯你用的是什么版本的Java啊?我刚刚实验了一下,没有这个问题啊~?
附上Code:
class A {
	public A(){
		draw();
	}
	public void  draw(){
		System.out.println("Father's method");
	}
}

public class TExtend {
	public int i = 1;  
    public TExtend(int i){  
        this.i=i;  
    }  
    public void draw(){  
        System.out.println("Son's method");
        System.out.println("i = " + i);  
    }  
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("In Main");
		TExtend te = new TExtend(5);
	}

}


2 楼 len-len 2012-02-27  
可以这么理解,也可以另外的方式理解,不是因为覆盖而去执行的,是因为是创建的是B对象,是由B对象决定调用方法。也就是我最后三句话中的第一句。谢谢这位童鞋的支持。
1 楼 yangnanenana 2012-02-27  
当执行  B b = new B(5);的时候,是不是先调用了A的构造器,但是A的构造器中的draw()方法因为被B覆盖了,所以调用的却是B中的draw()方法?
是不是可以这样理解?

相关推荐

    Java开发者文档,分享日常学习的一些小知识点 .rar

     在创建对象时,对象所在类的所有数据成员会首先进行初始化。  基本类型:int型,初始化为0。  如果为对象:这些对象会按顺序初始化。  ※在所有类成员初始化完成之后,才调用本类的构造方法创建对象。  ...

    JAVA基础知识精华总结 收藏

    在创建对象时,对象所在类的所有数据成员会首先进行初始化。 基本类型:int型,初始化为0。 如果为对象:这些对象会按顺序初始化。 ※在所有类成员初始化完成之后,才调用本类的构造方法创建对象。 构造方法的...

    Thinking in java4(中文高清版)-java的'圣经'

    5.6.1 指定初始化 5.7 构造器初始化 5.7.1 初始化顺序 5.7.2. 静态数据的初始化 5.7.3. 显式的静态初始化 5.7.4. 非静态实例初始化 5.8 数组初始化 5.8.1 可变参数列表 5.9 枚举类型 5.10 总结 第6章 访问权限控制 ...

    Java 基础核心总结 +经典算法大全.rar

    类的初始化 成员初始化 构造器初始化初始化顺序 数组初始化 对象的销毁 对象作用域 this 和 super 访问控制权限继承 多态组合代理 向上转型static final 接口和抽象类接口 抽象类异常 认 识 Exception 什么是 ...

    Java开发技术大全(500个源代码).

    errorInit.java 演示变量初始化错误的程序 integerExample.java 演示各种整型变量的使用 isPrime.java 判断素数 leapYearByIf.java 用if语句判断闰年 leapYearByLogical.java 用逻辑表达式判断闰年 lowToUpper...

    java联想(中文)

    7.5.4 初始化接口中的字段 7.6 内部类 7.6.1 内部类和上溯造型 7.6.2 方法和作用域中的内部类 7.6.3 链接到外部类 7.6.4 static内部类 7.6.5 引用外部类对象 7.6.6 从内部类继承 7.6.7 内部类可以覆盖吗? 7.6.8 ...

    Thinking in Java简体中文(全)

    7.5.4 初始化接口中的字段 7.6 内部类 7.6.1 内部类和上溯造型 7.6.2 方法和作用域中的内部类 7.6.3 链接到外部类 7.6.4 static内部类 7.6.5 引用外部类对象 7.6.6 从内部类继承 7.6.7 内部类可以覆盖吗? 7.6.8 ...

    疯狂JAVA讲义

    5.3.2 成员变量的初始化和内存中的运行机制 128 5.3.3 局部变量的初始化和内存中的运行机制 130 5.3.4 变量的使用规则 130 5.4 隐藏和封装 132 5.4.1 理解封装 132 5.4.2 使用访问控制符 132 5.4.3 package和...

    JAVA面试题解惑系列合集

    1.1 JAVA面试题解惑系列(一)——类的初始化顺序 1.2 JAVA面试题解惑系列(二)——到底创建了几个String对象? 1.3 JAVA面试题解惑系列(三)——变量(属性)的覆盖 1.4 JAVA面试题解惑系列(四)——final、...

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

    创建对象包括声明、实例化和初始化三方面的内容。通常的格式为 : 1. 声明对象 对象声明实际上是给对象命名,也称定义一个实例变量。对象声明的一般格式为: type name 其中,type 是一个类的类名,用它声明的对象将...

    java基础核心总结归纳---参考手册--心得手册-学习资料-总结经验

    初始化顺序 16 this 和 super 16 访问控制权限 16 继承 17 多态 17 代理 17 Static 17 Final 17 接⼝和抽象类 18 接⼝ 18 抽象类 18 异常 18 认识 Exception 18 什么是 Throwable 18 常⻅的 Exception 19 与 ...

    Thinking in Java 中文第四版+习题答案

    7.5.4 初始化接口中的字段 7.6 内部类 7.6.1 内部类和上溯造型 7.6.2 方法和作用域中的内部类 7.6.3 链接到外部类 7.6.4 static内部类 7.6.5 引用外部类对象 7.6.6 从内部类继承 7.6.7 内部类可以覆盖吗? 7.6.8 ...

    java 面试题 总结

    对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实现的实体。 Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session ...

    Thinking in java(中文)

    <br>第2章 一切都是对象 2.1 用句柄操纵对象 2.2 必须创建所有对象 2.2.1 保存在什么地方 2.2.2 特殊情况:主类型 2.2.3 Java中的数组 2.3 绝对不要清除对象 2.3.1 作用域 2.3.2 对象的...

    java 编程入门思考

    7.5.4 初始化接口中的字段 7.6 内部类 7.6.1 内部类和上溯造型 7.6.2 方法和作用域中的内部类 7.6.3 链接到外部类 7.6.4 static内部类 7.6.5 引用外部类对象 7.6.6 从内部类继承 7.6.7 内部类可以覆盖吗? 7.6.8 ...

    Java初学者入门教学

    7.5.4 初始化接口中的字段 7.6 内部类 7.6.1 内部类和上溯造型 7.6.2 方法和作用域中的内部类 7.6.3 链接到外部类 7.6.4 static内部类 7.6.5 引用外部类对象 7.6.6 从内部类继承 7.6.7 内部类可以覆盖吗? 7.6.8 ...

    java初学者必看

    6.2.2 二维数组的初始化 6.2.3 二维数组的空间模型 6.2.4 二维数组的使用 6.3 数组操作 6.3.1 排序数组 6.3.2 查找 6.3.3 复制数组 6.3.4 填充数据 6.3.5 比较数组 6.4 实例:杨辉三角 6.5 本章习题 第7...

    JAVA_Thinking in Java

    7.5.4 初始化接口中的字段 7.6 内部类 7.6.1 内部类和上溯造型 7.6.2 方法和作用域中的内部类 7.6.3 链接到外部类 7.6.4 static内部类 7.6.5 引用外部类对象 7.6.6 从内部类继承 7.6.7 内部类可以覆盖吗? 7.6.8 ...

    超级有影响力霸气的Java面试题大全文档

     对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实现的实体。  Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless ...

    JAVA基础课程讲义

    创建数组和初始化 106 数组常见操作 108 数组的拷贝 108 数组排序 109 多维数组 110 附录(面试前复习一下!!) 111 冒泡排序 111 二分法查找 112 命令行参数的问题 113 增强for循环 114 思考作业 114 上机作业 115 ...

Global site tag (gtag.js) - Google Analytics