java编程思想读书笔记(3)--关于对象初始化的一些迷惑

来源:互联网 发布:手机视频编辑软件 编辑:程序博客网 时间:2024/05/01 08:49

1、以下是编程思想中的一段代码,开始看时还是有点迷惑的。

abstract class Glyph {   abstract void draw();   Glyph() {     System.out.println("Glyph() before draw()");     draw();      System.out.println("Glyph() after draw()");   } }  class RoundGlyph extends Glyph {   int radius = 1;   RoundGlyph(int r) {     radius = r;     System.out.println(       "RoundGlyph.RoundGlyph(), radius = "       + radius);   }   void draw() {      System.out.println(       "RoundGlyph.draw(), radius = " + radius);   } }  public class PolyConstructors {   public static void main(String[] args) {     new RoundGlyph(5);   } }


执行结果:

Glyph() before draw() RoundGlyph.draw(), radius = 0 Glyph() after draw() RoundGlyph.RoundGlyph(), radius = 5

书中给出的解释是:

初始化的实际过程是这样的:
(1) 在采取其他任何操作之前,为对象分配的存储空间初始化成二进制零。
(2) 就象前面叙述的那样,调用基础类构建器。此时,被覆盖的draw()方法会得到调用(的确是在
RoundGlyph构建器调用之前),此时会发现radius的值为0,这是由于步骤(1)造成的。
(3) 按照原先声明的顺序调用成员初始化代码。
(4) 调用衍生类构建器的主体

计构建器时一个特别有效的规则是:用尽可能简单的方法使对象进入就绪状态;如果可能,避免调用任何方法。在构建器内唯一能够安全调用的是在基础类中具有final属性的那些方法(也适用于private方法,它们自动具有final属性)。这些方法不能被覆盖,所以不会出现上述潜在的问题。

 

2、关于上面的例子,我就在想为什么能在构造方法里面能调用类的方法呢?类的方法不是需要对象调用吗?构造方法还没执行完对象其实已经创建成功了吗?this对象已经存在了吗?

对于以上的问题,我询问了一些人,然后也查看了一些资料,看了这个博客以后,我豁然开朗了,原来new是创建对象,后面的***() 是初始化对象,也就是调用构造方法之前,对象已经存在了,所以构造方法中能够使用this关键字,而static方法由于不用创建对象,即无法使用关键字this。

http://lipan0424.blog.163.com/blog/static/20811629020125173199827/

 

我以前一直以为空着大括号的构造函数只是象征的意思一下,根本起不来给对象初始化的作用,我以为那些成员变量的值不在大括号里赋值,就不是构造函数给他初始化的,现在想来错了,所有一切初始化的值都是构造函数完成的,即使你是把赋值语句写在构造函数外。

 

3、1) 装载阶段由三个基本动作组成: 
    ① 通过该类型的完全限定名,产生一个代表该类型的二进制数据流。 
    ② 解析这个二进制数据流为方法区内的内部数据结构。 
    ③ 创建一个表示该类型的java.lang.Class类的实例。 

     如果一个类装载器在预先装载时遇到缺失或者错误的class文件,它必须等到程序首次主动使用该类时才报告错误,如果一个类一直没有被程序主动使用,那么该类装载器就不会报告错误。 
      2) 验证,类型被转载后,就准备进行连接了,连接过程的第一步是验证,确认类型符合Java语言的语义,并且他不会危及虚拟机的完整性。 
      3) 准备阶段,Java虚拟机为类变量分配内存,设置默认初始值,虚拟机把给类变量新分配的内存根据类型设置为默认值。准备阶段,Java虚拟机实现可能也为一些数据结构分配内存,目的是提高运行程序的性能。 
      4) 解析过程就是在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用换成直接引用的过程。 
      5) 初始化就是为类变量赋予正确的初始值,“正确”初始值指的是程序员希望这个类变量所具备的起始值,正确的初始值是和在准备阶段赋予的默认初始值对比而言的。

 

回过头来想想当使用 new ***(); 时 ,先初始化这个类,会执行3中的初始化过程,为程序中一些变量赋上默认的初始值 int为0 等,然后就是new这个对象,对象创建成功后,执行构造方法去初始化一些变量,也就是让变量的默认值变成程序中你赋上的值。就算构造方法为空,也会在其中初始化。