美文网首页
《疯狂JAVA讲义》第四版 -> BUG

《疯狂JAVA讲义》第四版 -> BUG

作者: 蝉鸣的雨 | 来源:发表于2020-07-03 17:04 被阅读0次

P159 第二个注意框里,有关代码块的描述如下:

实际上初始化块是一个假象,使用 Javac 命令编译 Java 类后,该 Java 类中的初始化 一: 块会消失---初始化块中代码会被"还原"到每个构造器中,且位于构造器所有代码的 南 前面 。

然后经过代码检验,发现此处的描述初始化块中代码会被"还原"到每个构造器中有误,测试代码如下:

public class InitializeDemo {

    private String name;
    private int age;

    {
        this.name = "william";
        this.age = 10;
    }

    public InitializeDemo() {
    }

    public static void main(String[] args) {
        InitializeDemo demo = new InitializeDemo();
        System.out.println(demo.getName());
        System.out.println(demo.getAge());
    }
    // 省略getter setter
}

编译后的class文件中的代码经过反编译后,为

public class InitializeDemo {
    private String name = "william";
    private int age = 10;

    public InitializeDemo() {
    }

    public static void main(String[] args) {
        InitializeDemo demo = new InitializeDemo();
        System.out.println(demo.getName());
        System.out.println(demo.getAge());
    }
    // 省略getter setter
}

发现编译后的代码块中的内容,并未还原到构造器中,而是添加到了成员变量中。

那么,什么情况下,才会将代码块中的定义还原到构造器中呢?如下测试:

public class InitializeDemo {

    private String name;
    private int age;

    {
        setName("william");
        setAge(10);
    }

    public InitializeDemo() {
    }
    // getter setter 等其他代码
}

此时编译后的class文件为:

public class InitializeDemo {
    private String name;
    private int age;

    public InitializeDemo() {
        this.setName("william");
        this.setAge(10);
    }

    public static void main(String[] args) {
        InitializeDemo demo = new InitializeDemo();
        System.out.println(demo.getName());
        System.out.println(demo.getAge());
    }
    // getter setter 等其他代码
}

此时的变量初始化就被编译到了构造器中了。

其原因可通过类初始化过程解释。但是书中并未指明这两种方式的区别,笼统的按第二种方式来解释,可见不太严谨。

相关文章

网友评论

      本文标题:《疯狂JAVA讲义》第四版 -> BUG

      本文链接:https://www.haomeiwen.com/subject/cznsqktx.html