2 zyf4005 zyf4005 于 2016.05.07 08:23 提问

关于java中加载和初始化的疑问?各位帮忙分析下

public class ExA {

private static ExA a = new ExA();
static {
    System.out.println("父类--静态代码块");
}

 public ExA() {
    System.out.println("父类--构造函数");
}

{
    System.out.println("父类--非静态代码块");
}

public static void main(String[] args) {
    new ExB();
}

}
程序执行时先找到程序入口即main函数,接着加载和初始化main函数所在的类即ExA,那么第一句就是private static ExA a = new ExA();那么执行这句代码的时候发生了什么?我知道的是先把a设置为null,然后才去赋值为new ExA();关键是new ExA()(第一次创建对象)的时候按道理不是会触发ExA类的加载和初始化吗?但这句代码就在ExA类初始化的第一行,难道要跳过去初始化static { System.out.println("父类--静态代码块"); }吗?还是有别的理解?
第二个疑问:是不是当要首次创建一个类的对象时,前提条件是这个类必须先加载和初始化都完成后才能首次创建类的对象?还是说只要这个类加载了虽然没有初始化就可以创建类的对象了?

class ExB extends ExA {

private static ExB b = new ExB();
static {
    System.out.println("子类--静态代码块");
}
{
    System.out.println("子类--非静态代码块");
}

public ExB() {
    System.out.println("子类--构造函数");
}

}

5个回答

wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.05.09 12:42
已采纳

首先,你注释掉这两个类中所有的静态代码块,执行代码,可以看到类的实例化过程中,父类、子类非静态代码库、构造函数调用的顺序了。
非静态代码块和构造函数,都是用来实例化类时初始化类的成员变量的,即init(){ 非静态代码块+构造函数},而且非静态代码块总是在构造函数之前调用的。

 父类--非静态代码块
父类--构造函数
子类--非静态代码块
子类--构造函数

其次,静态代码块,在这个类第一次被调用或实例化的时候就会被执行。 静态代码块只会执行一次,一般会用来初始化一些值,并且在所有对象中全局共享。比如:你注释掉所有代码,如下:直接执行空的main函数时,ExA类被加载时就会执行静态代码块:

 public class ExA {

    static {
        System.out.println("父类--静态代码块");
    }


    public static void main(String[] args) {

    }

}

因为你是ExA中的main方法,加载这个类时就会执行这个类的静态代码块。
你的第二个问题,我们在使用一个类之前,它必须经过装载,连接,初始化这样的过程。然后我们才能使用new操作实例化创建对象,它的初始化就是执行类的静态代码块,完成全局属性的设置。我认为构造函数则是实例化创建对象时调用的,跟类的初始化不是一个概念的。
参考链接:blog.csdn.net/moreevan/article/details/6968718

zyf4005
zyf4005 那么我的疑问是你既然说“我们在使用一个类之前,它必须经过装载,连接,初始化这样的过程。然后我们才能使用new操作实例化创建对象,”那么代码的第一句private static ExA a = new ExA();这时候类ExA还没有加载和初始化完成呢,那岂不是就无法new ExA()了吗?
一年多之前 回复
niaonao
niaonao   Rxr 2016.05.07 11:29

在main 开始之前先执行一次 类加载
(且只执行一次,执行的是相关的静态代码块或函数)

然后找main 入口开始执行

yonghuwangwei
yonghuwangwei   2016.05.09 11:31

静态代码块或函数是由java虚拟机执行的,且只在加载到内存时执行一次,先执行private static ExA a = new ExA();,因为有new所以转而执行非静态代码
和构造方法(应为此时是同一个类的初始化过程中,所以new的时候不会执行静态代码,静态代码由new完之后的虚拟机执行,同时静态代码是公共的),接着
执行静态代码,接着new一个给子类,所以执行非静态代码和构造方法。

zyf4005
zyf4005 本来执行private static ExA a = new ExA();的时候因为是首次new,所以会导致类ExA的加载和初始化。因为此时有main导致的类的加载和初始化。这两个初始化是一个类,所以才去执行了非静态代码。那你的意思可以理解为在类的加载和初始化过程中就可以创建对象,没有要求说:类必须加载和初始化完成后才能创建对象是吧?
一年多之前 回复
havedream_one
havedream_one   2016.05.09 19:49
public class Test20160509 {
    public static int k = 5;
    public static Test20160509 t1 = new Test20160509("t1");
    public static Test20160509 t2 = new Test20160509("t2");
    public static String s = "abcd";
    public static int i = print("i");
    public static int n = 99;

    public int j = print("j");

    {
        print("非静态构造块");
    }

    static {
        print("静态块");
    }

    public Test20160509(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n + "   str=" + s + "  t1=" + t1 + "   t2=" + t2);
        ++i;
        ++n;
    }

    private static int print(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "   n=" + n + "   str=" + s + "  t1=" + t1 + "   t2=" + t2);
        ++n;
        return ++i;
    }

    public static void main(String[] args) {
        Test20160509 t = new Test20160509("init");
        Test20160509 t2 = new Test20160509("init2");

    }

}

图片说明

havedream_one
havedream_one   2016.05.09 19:49
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!