烦劳各位能比较详细的讲讲java中初始化顺序的问题.只有70分,全部送上了。谢谢了!比如说
自己是基类的情况:静态字段,静态块(static block),实例变量,静态方法,实例方法,构造函数,它们的初始化顺序。
自己是子类的情况:父类的(静态字段,静态块(static block),实例变量,静态方法,实例方法,构造函数,它们的初始化顺序。
) 子类的(静态字段,静态块(static block),实例变量,静态方法,实例方法,构造函数,它们的初始化顺序。
),此时父类内部初始化顺序,与本身是基类时的初始化顺序有没有不同的地方?
自己是基类的情况:静态字段,静态块(static block),实例变量,静态方法,实例方法,构造函数,它们的初始化顺序。
自己是子类的情况:父类的(静态字段,静态块(static block),实例变量,静态方法,实例方法,构造函数,它们的初始化顺序。
) 子类的(静态字段,静态块(static block),实例变量,静态方法,实例方法,构造函数,它们的初始化顺序。
),此时父类内部初始化顺序,与本身是基类时的初始化顺序有没有不同的地方?
public class Init
{
public static void main(String... args) {
System.out.println(new Base().i); //output: 5 10
System.out.println(new Drive().j);//output: 0 6 16
}
}class Base
{
int i = 5;
public Base() {
fun();
i = 10;
}
public void fun() {
System.out.println(i);
}
}class Drive extends Base
{
int j = 6;
public Drive() {
fun();
j = 16;
}
public void fun() {
System.out.println(j);
}
}
基类初始化时为5
而子类初始化时为0 ?
2,按对象的尺寸在堆中分配一块恰好能放入对象的内存,并对这块内存清零。
3,
3.1 过构造方法递归调用父类的默认构造方法,如果父类没有默认的构造方法,你必需明确指定用那个构造方法。直到Object。
3.2 递归过程中,各级构造方法的直接父类构选方法执行完后,再对本类的其它属性按指定的值初始化,
3.3 递归过程中,执行完3.2后,再执行本类的构造方法中的语句。
4,完全对象的构造。这是我知道的顺序,不太清楚初始化语句快是在什么时候执行的。
在一个类里面有一个int的属性a
如 int a = 7;
是不是先把a 赋一个默认的初始值0然后再赋7呢?
建议LZ看下 深入JVM原理吧。你会有很大的收获的
2.然后我们写好了一个类的子类继承父类 通过 new 方法构造子类对象,首先会初始化父类的成员变量,然后调用父类的构造方法。
3.父类的构造方法完成后。线程会回到你的子类中,和之前初始化父类顺序一样,先初始化子类成员变量。在执行子类构造方法。产生出子类的对象(注明:父类的对象已经包括在子类对象中了!通过Super可以调用)
4.如果在父类中的成员方法被子类重写过,那么在父类中调用的是子类中重写过的方法(这就是所谓的多态性!也是为什么你说得"而子类初始化时为0 "因为在你的父类构造函数中调用调用的fun()方法并不是父类的fun(),而是子类的fun(),而这时子类的初始化过程还没开始,因此子类中的"j"还只是默认的"0"!所以你打印的结果会让你感觉困惑!呵呵)这是我的个人对初始化顺序的一个理解。如果不足请高手指出!
这一段我是猜的。应该再求证一下。如果我猜的是对的。你的结果就有了解释了。
Java代码
public class InitialOrderTest {
// 静态变量
public static String staticField = "静态变量";
// 变量
public String field = "变量";
// 静态初始化块
static {
System.out.println(staticField);
System.out.println("静态初始化块");
}
// 初始化块
{
System.out.println(field);
System.out.println("初始化块");
}
// 构造器
public InitialOrderTest() {
System.out.println("构造器");
}
public static void main(String[] args) {
new InitialOrderTest();
}
} 运行以上代码,我们会得到如下的输出结果: 静态变量
静态初始化块
变量
初始化块
构造器 这与上文中说的完全符合。那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:
Java代码
class Parent {
// 静态变量
public static String p_StaticField = "父类--静态变量";
// 变量
public String p_Field = "父类--变量";
// 静态初始化块
static {
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}
// 初始化块
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
}
// 构造器
public Parent() {
System.out.println("父类--构造器");
}
}
public class SubClass extends Parent {
// 静态变量
public static String s_StaticField = "子类--静态变量";
// 变量
public String s_Field = "子类--变量";
// 静态初始化块
static {
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
}
// 初始化块
{
System.out.println(s_Field);
System.out.println("子类--初始化块");
}
// 构造器
public SubClass() {
System.out.println("子类--构造器");
}
// 程序入口
public static void main(String[] args) {
new SubClass();
}
} 运行一下上面的代码,结果马上呈现在我们的眼前: 父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器 现在,结果已经不言自明了。大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。 那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?实际上这取决于它们在类中出现的先后顺序。我们以静态变量和静态初始化块为例来进行说明。 同样,我们还是写一个类来进行测试:
Java代码
public class TestOrder {
// 静态变量
public static TestA a = new TestA();
// 静态初始化块
static {
System.out.println("静态初始化块");
}
// 静态变量
public static TestB b = new TestB();
public static void main(String[] args) {
new TestOrder();
}
}
class TestA {
public TestA() {
System.out.println("Test--A");
}
}
class TestB {
public TestB() {
System.out.println("Test--B");
}
} 运行上面的代码,会得到如下的结果: Test--A
静态初始化块
Test--B 大家可以随意改变变量a、变量b以及静态初始化块的前后位置,就会发现输出结果随着它们在类中出现的前后顺序而改变,这就说明静态变量和静态初始化块是依照他们在类中的定义顺序进行初始化的。同样,变量和初始化块也遵循这个规律。