JAVA面试题解惑系列(一)——类的初始化顺序-JAVA程序员JAVA工程师面试必看

合集下载

java类的初始化顺序

java类的初始化顺序

java类的初始化顺序
类在使⽤时,会加载进内存⾥,然后进⾏成员属性等初始化。

顺序:
1、在加载完后,所有成员属性都会有⼀个默认值,会在存储空间初始化为⼆进制的0。

2、按照定义顺序,初始化⽗类静态属性和静态代码块,如果⽗类还有⽗类,⼀直逆向初始化⽗类,直⾄根⽗类
3、按照定义顺序,初始化⼦类静态属性和静态代码块
4、按照定义顺序,初始化⽗类普通属性和普通代码块
5、执⾏⽗类构造器
6、按照定义顺序,初始化⼦类普通属性和普通代码块
7、执⾏⼦类构造器
总体⽽⾔,先⽗类,后⼦类;先静态属性,后普通属性;先属性,后构造器。

注意:
1、静态属性只初始化⼀次,在第⼀次使⽤时初始化后,⽆论创建多少次对象,都不会再初始化。

2、关于构造器:
1)如果在类中,没有定义构造器,编译器会⾃动创建⼀个⽆参构造器。

反之,如果定义了构造器,编译器就不会再添加⽆参构造器了。

2)如果⽗类只定义了有参构造器,⽽没有⽆参构造器,并且在⼦类中没有显⽰调⽤⽗类的有参构造器,则在初始化时会报错。

因在⼦类中,默认会调⽤⽗类的⽆参构造器,⽽⽗类没有⽆参构造器,就出错了。

java类变量初始化顺序

java类变量初始化顺序

java类变量初始化顺序假定有⼀个类定义如下:package com.zhang;public final class Girl {// static代码块1private static String sex = "female";// 成员⽅法代码块1private String name = "anonymous";// static代码块2static {System.out.println("static1");}// 成员⽅法代码块3public Girl() {System.out.println("constructor");}// static代码块3static {System.out.println("static2");}// 成员⽅法代码块2private int age = 18;}第⼀次加载类,并创建该类对象时,静态变量、成员变量的初始化顺序,静态代码的执⾏顺序是怎样的?创建⼀个类对象,如果该类没有初始化,则先初始化该类(执⾏ clinit ⽅法),然后执⾏构造函数(init ⽅法),具体就是先执⾏ class ⽂件中的 static 代码块,然后再执⾏构造函数代码块。

观察上⾯类的 class ⽂件 static 代码块:可以看出,static 代码块内容就是,把 static 语句按顺序搜集起来,static 变量赋值也是 static 语句,伪代码如下:static {sex = "female";System.out.println("static1");System.out.println("static2");}构造函数代码块:对应的伪代码如下:public Girl() {<init>name = "anonymous";age = 18;System.out.println("constructor");}⾸先执⾏ <init> ⽅法,即按顺序收集构造函数外部的语句,然后再执⾏构造函数内的语句。

java对象的初始化顺序

java对象的初始化顺序

对象初始化流程:我们根据一段代码来分析对象初始化流程:/***基类包含一静态变量、包含一实例变量*包含一个静态初始化块以及一个构造子*/class Base{public static int a = 10;public int b = 20;static{System.out.println("Static Init Base " + a);//System.out.println("Null Init " + b);}public Base(){System.out.println("Init Base " + this.b);}}/***一级子类和基类包含的内容一样**/class SuperClass extends Base{public static int a1 = getSuperStaticNumber();public int b1 = getSuperInstanceNumber();public SuperClass(){System.out.println("Init SuperClass" + this.b1); }static{System.out.println("Static Init SuperClass" + a1); }public static int getSuperStaticNumber(){System.out.println("Static member init");return 100;}public int getSuperInstanceNumber(){System.out.println("Instance member init");return 200;}}/***二级子类为测试该代码的驱动类*/public class SubClass extends SuperClass{public static int a2 = getStaticNumber();public int b2 = getInstanceNumber();public SubClass(){System.out.println("Init SubClass " + this.b2);}public static int getStaticNumber(){System.out.println("Static member init Sub");return 1000;}public int getInstanceNumber(){System.out.println("Instance member init Sub");return 2000;}public static void main(String args[]){new SubClass();}static{System.out.println("Static Init " + a2);}}这段代码会有以下输出:Static Init Base 10Static member initStatic Init SuperClass 100Static member init SubStatic Init 1000Init Base 20Instance member initInit SuperClass 200Instance member init SubInit SubClass 2000[1]对象在初始化过程,JVM会先去搜索该类的顶级父类,直到搜索到我们所定义的SubClass继承树上直接继承于Object类的子类,在这里就是Base 类;[2]然后JVM会先加载Base类,然后初始化Base类的静态变量a,然后执行Base类的静态初始化块,按照这样第一句话会输出:Static Init Base 10【*:此时该类还未调用构造函数,构造函数是实例化的时候调用的】[3]然后JVM按照继承树往下搜索,继续加载Base类的子类,按照静态成员函数->静态成员变量->静态初始化块的顺序往下递归,直到加载完我们使用的对象所在的类。

Java初始化顺序

Java初始化顺序

Java初始化顺序/thread.shtml?topicId=36138&forumId=19初始化(initialization)其实包含两部分:1.类的初始化(initialization class & interface)2.对象的创建(creation of new class instances)。

因为类的初始化其实是类加载(loading of classes)的最后一步,所以很多书中把它归结为“对象的创建”的第一步。

其实只是看问题的角度不同而已。

为了更清楚的理解,这里还是分开来。

顺序:类的加载肯定是第一步的,所以类的初始化在前。

大体的初始化顺序是:类初始化-> 子类构造函数-> 父类构造函数-> 实例化成员变量-> 继续执行子类构造函数的语句下面结合例子,具体解释一下。

1。

类的初始化(Initialization classes and interfaces),其实很简单,具体来说有:(a)初始化类(initialization of class),是指初始化static field 和执行static初始化块。

例如:class Super {static String s = “initialization static field”; //初始化static field,其中“= “initialization static field” ”又叫做static field initializer// static初始化块,又叫做static initializer,或static initialization blockstatic{System.out.println(“This is static initializer”);}}btw,有些书上提到static initializer和static field initializer的概念,与之对应的还有instance initializer和instance variable initializer。

java初始化顺序

java初始化顺序
JAVA初始化顺序
JAVA类首次装入时,会对静态成员变量或方法进行一次初始化,但方法不被调用是不会执行的,静态成员变量和静态初始化块级别相同,非静态成员变量和非静态初始化块级别相同。
先初始化父类的静态代码--->初始化子类的静态代码-->??
(创建实例时,如果不创建实例,则后面的不执行)初始化父类的非静态代码--->初始化父类构造函数--->初始化子类非静态代码--->初始化子类构造函数?
2. 子类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行
3. 父类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行
4. 父类构造方法
5. 子类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行
ห้องสมุดไป่ตู้
2、类只有在使用New调用创建的时候才会被JAVA类装载器装入
3、创建类实例时,首先按照父子继承关系进行初始化
类实例创建时候,首先初始化块部分先执行,然后是构造方法;然后从本类继承的子类的初始化块执行,最后是子类的构造方法??
5、类消除时候,首先消除子类部分,再消除父类部分
1. 父类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行

java类的加载顺序(面试题)

java类的加载顺序(面试题)

java类的加载顺序(⾯试题)
初始化:
1. 静态属性:static 开头定义的属性
2. 静态⽅法块: static {} 圈起来的⽅法块
3. 普通属性:未带static定义的属性
4. 普通⽅法块: {} 圈起来的⽅法块
5. 构造函数:类名相同的⽅法
6. ⽅法:普通⽅法
实例化:按照上⾯的顺序,但是不重新加载静态修饰的属性以及⽅法了,因为第⼀次初始化的时候,已经被加载过了,可以直接调⽤。

直接运⾏2,3,4,5,6
普通类:
静态变量
静态代码块
普通变量
普通代码块
构造函数
继承的⼦类:
⽗类静态变量
⽗类静态代码块
⼦类静态变量
⼦类静态代码块
⽗类普通变量
⽗类普通代码块
⽗类构造函数
⼦类普通变量
⼦类普通代码块
⼦类构造函数
抽象的实现⼦类: 接⼝ - 抽线类 - 实现类
接⼝静态变量
抽象类静态变量
抽象类静态代码块
实现类静态变量
实习类静态代码块
抽象类普通变量
抽象类普通代码块
抽象类构造函数
实现类普通变量
实现类普通代码块
实现类构造函数
接⼝注意:
声明的变量都是静态变量并且是final的,所以⼦类⽆法修改,并且是固定值不会因为实例⽽变化
接⼝中能有静态⽅法,不能有普通⽅法,普通⽅法需要⽤defalut添加默认实现
接⼝中的变量必须实例化
接⼝中没有静态代码块、普通变量、普通代码块、构造函数。

java变量初始化顺序

java变量初始化顺序

java变量初始化顺序第⼀次实例化⼀个类时,初始化优先顺序为:1、⽗类中的静态成员变量和静态代码块初始化2、本类中的静态成员变量和静态代码块初始化3、⽗类中的实例成员初始化4、⽗类中的构造⽅法5、本类中的实例成员初始化6、本类中的构造⽅法成员变量和⽰例变量初始化的区别: 成员变量:每次新建对象的时候都会初始化; 实例变量:只在第⼀次调⽤(包括实例化或通过类访问)的时候⼀次性初始化全部的静态变量 实例变量⽰例:class Tag {Tag(int marker) {System.out.println("Tag(" + marker + ")");}}class Card {Tag t1 = new Tag(1); // Before constructorCard() { // Indicate we're in the constructor:System.out.println("Card()");t3 = new Tag(33); // Re-initialize t3}Tag t2 = new Tag(2); // After constructorvoid f() {System.out.println("f()");}Tag t3 = new Tag(3); // At end}public class OrderOfInitialization {public static void main(String[] args) {Card t = new Card();t.f(); // Shows that construction is done}}运⾏结果: Tag(1) Tag(2) Tag(3) Card() Tag(33) f()静态变量⽰例:public class Bowl {Bowl(int marker) {System.out.println("Bowl(" + marker + ")");}void f(int marker) {System.out.println("f(" + marker + ")");}}public class Table {static Bowl b1 = new Bowl(1);Table() {System.out.println("Table()");b2.f(1);}void f2(int marker) {System.out.println("f2(" + marker + ")");}static Bowl b2 = new Bowl(2);}public class Cupboard {Bowl b3 = new Bowl(3);//注意实例变量与静态变量共存的时候,即使静态变量靠后,也先初始化static Bowl b4 = new Bowl(4);Cupboard() {System.out.println("Cupboard()");b4.f(2);}void f3(int marker) {System.out.println("f3(" + marker + ")");}static Bowl b5 = new Bowl(5);}public class Test {public static void main(String[] args) throws Exception { System.out.println("Creating new Cupboard() in main");new Cupboard();System.out.println("Creating new Cupboard() in main");new Cupboard();t2.f2(1);t3.f3(1);}static Table t2 = new Table();static Cupboard t3 = new Cupboard();}运⾏结果:Bowl(1)Bowl(2)Table()f(1)Bowl(4)Bowl(5)Bowl(3)Cupboard()f(2)Creating new Cupboard() in mainBowl(3)Cupboard()f(2)Creating new Cupboard() in mainBowl(3)Cupboard()f(2)f2(1)f3(1)。

Java初始化顺序(静态变量、静态初始化块、实例变量、实例初始化块、构造方法)

Java初始化顺序(静态变量、静态初始化块、实例变量、实例初始化块、构造方法)

Java初始化顺序(静态变量、静态初始化块、实例变量、实例初始化块、构造⽅法)1、执⾏顺序1.1、⼀个类中的初始化顺序类内容(静态变量、静态初始化块) => 实例内容(变量、初始化块、构造器)1.2、两个具有继承关系类的初始化顺序⽗类的(静态变量、静态初始化块)=> ⼦类的(静态变量、静态初始化块)=> ⽗类的(变量、初始化块、构造器)=> ⼦类的(变量、初始化块、构造器)⽰例如下:(结果见注释)1class A {2public A() {3 System.out.println("Constructor A.");4 }56 {7 System.out.println("Instance Block A.");8 }9static {10 System.out.println("Static Block A.");11 }1213public static void main(String[] args) {14new A();/*15 * Static Block A. Instance Block A. Constructor A.16*/17 }18 }1920class B extends A {21public B() {22 System.out.println("Constructor B.");23 }2425 {26 System.out.println("Instance Block B.");27 }28static {29 System.out.println("Static Block B.");30 }3132public static void main(String[] args) {33new A();/*34 * Static Block A. Static Block B. Instance Block A. Constructor A.35*/36 System.out.println();37new B();/*38 * Instance Block A. Constructor A. Instance Block B. Constructor B.39*/// 静态成员和静态初始化块只会执⾏⼀次。

Java中class的初始化顺序

Java中class的初始化顺序

Java中class的初始化顺序 由于Java 中的⼀切东西都是对象,所以许多活动变得更加简单,这个问题便是其中的⼀例。

除⾮真的需要代码,否则那个⽂件是不会载⼊的。

通常,我们可认为除⾮那个类的⼀个对象构造完毕,否则代码不会真的载⼊。

由于static ⽅法存在⼀些细微的歧义,所以也能认为“类代码在⾸次使⽤的时候载⼊”。

⾸次使⽤的地⽅也是static 初始化发⽣的地⽅。

装载的时候,所有static 对象和static 代码块都会按照本来的顺序初始化(亦即它们在类定义代码⾥写⼊的顺序)。

当然,static 数据只会初始化⼀次。

简要的说就是,在类有继承关系时,类加载器上溯造型,进⾏相关类的加载⼯作。

⽐如:Class B extends Class A当我们new B()时,类加载器⾃动加载A的代码class的初始化顺序通常是以下这样的初始化顺序:(static对象和static代码块,依据他们的顺序进⾏初始化)->成员变量和代码块(依据他们的顺序进⾏初始化)->构造函数例如:package cn.d;public class ClassInit {public static void main(String[] args) {new B();System.out.println("------------");new B();}}class A {static {System.out.println("A的static代码块...");// 1}{System.out.println("A的代码块...");// 1}public String s1 = prtString("A的成员变量...");public static String s2 = prtString("A的static变量...");// 2public A() {System.out.println("A的构造函数...");}public static String prtString(String str) {System.out.println(str);return null;}}class B extends A {public String ss1 = prtString("B的成员变量...");{System.out.println("B的代码块...");}public static String ss2 = prtString("B的static变量...");// 3.public B() {System.out.println("B的构造函数...");}private static A a = new A();// 4.static {System.out.println("B的static代码块...");}}结果:A的static代码块...A的static变量...B的static变量...A的代码块...A的成员变量...A的构造函数...B的static代码块...A的代码块...A的成员变量...A的构造函数...B的成员变量...B的代码块...B的构造函数...------------A的代码块...A的成员变量...A的构造函数...B的成员变量...B的代码块...B的构造函数...解释:1. ⾸先加载A的静态代码快和静态变量,由于A中静态代码块刈写在前⾯,因此先加载静态代码块后加载静态变量。

java中类成员初始化顺序

java中类成员初始化顺序

java中类成员初始化顺序java中初始化类成员⽅法包括:1.显⽰域初始化,⽐如public int a=1;public static int b=1;2.初始化块,分为普通初始化块,静态初始化块;3.构造函数。

初始化的时候,⾸先是静态类的初始化⽅式执⾏,然后才是普通初始⽅式执⾏,并且初始化块总是先于构造函数执⾏,显式域初始化与初始化块的执⾏顺序按照代码中出现的顺序执⾏。

显式静态域初始化先于静态初始化块public class Hello{public static int staticA=1;public static int staticB;static{System.out.println("Static Inital Block Start");staticB=2;PrintAB();System.out.println("Static Inital Block End\n");}public static void PrintAB(){System.out.println("staticA:"+staticA);System.out.println("staticB:"+staticB);}public Hello(){Hello.PrintAB();}public static void main(String[] args){Hello h=new Hello();}}输出:Static Inital Block StartstaticA:1staticB:2Static Inital Block EndstaticA:1staticB:2显式静态域初始化后于静态初始化块public class Hello{public static int staticB;static{System.out.println("Static Inital Block Start");staticB=2;PrintAB();System.out.println("Static Inital Block End\n");}public static int staticA=1;public static void PrintAB(){System.out.println("staticA:"+staticA);System.out.println("staticB:"+staticB);}public Hello(){Hello.PrintAB();}public static void main(String[] args){Hello h=new Hello();}}输出:Static Inital Block StartstaticA:0staticB:2Static Inital Block EndstaticA:1staticB:2显式静态域初始化与初始化块按照出现顺序执⾏,最后执⾏构造函数, 注意noStaticD在两个构造快中间初始化,第⼀个初始化块打印时noStaticD=0,第⼆个块中变为1输出:NoStatic Inital Block for noStaticC StartnoStaticC:1noStaticD:1noStaticE:1noStaticF:0NoStatic Inital Block for noStaticC EndConstructor StartnoStaticC:1noStaticD:1noStaticE:1noStaticF:1Constructor END。

Java——对象初始化顺序使用详解

Java——对象初始化顺序使用详解

Java——对象初始化顺序使⽤详解⼀、代码块的概念在探究对象初始化顺序之前,我们先通过代码来了解⼀下代码块的概念。

class Test{public static String str1; //静态字段public String str2; //普通字段static{//静态代码块}{//构造代码块}public Test() {//构造函数}}⼆、创建⼦类对象时,对象的初始化顺序1. 字段初始化、代码块和构造函数的执⾏顺序我们先看代码和结果public class CodeBlockTest {public static void main(String[] args) {Child child = new Child();}}class Father {public static String fatherStr1 = "fatherStr1(静态字段初始化值)";public String fatherStr2 = "fatherStr2(字段初始化值)";static {System.out.println("⽗类静态代码块:" + fatherStr1);fatherStr1 = "fatherStr1(静态代码块赋值)";}{System.out.println("⽗类构造代码块:" + fatherStr2);fatherStr2 = "fatherStr2(构造代码块赋值)";}public Father() {System.out.println("⽗类构造函数块:" + fatherStr2);fatherStr2 = "fatherStr2(构造函数赋值)";}}class Child extends Father {public static String childStr1 = "childStr1(静态字段初始化值)";public String childStr2 = "childStr2(字段初始化值)";static {System.out.println("⼦类静态代码块:" + childStr1);childStr1 = "childStr1(静态代码块赋值)";}{System.out.println("⼦类构造代码块:" + childStr2);childStr2 = "childStr2(构造代码块赋值)";}public Child() {System.out.println("⼦类构造函数:" + childStr2);childStr2 = "childStr2(构造函数赋值)";}}// 输出结果:// ⽗类静态代码块:fatherStr1(静态字段初始化值)// ⼦类静态代码块:childStr1(静态字段初始化值)// ⽗类构造代码块:fatherStr2(字段初始化值)// ⽗类构造函数块:fatherStr2(构造代码块赋值)// ⼦类构造代码块:childStr2(字段初始化值)// ⼦类构造函数:childStr2(构造代码块赋值)通过每执⾏⼀个代码块或构造函数,输出字段在上⼀代码块执⾏后的值,以此来探究对象的初始化顺序。

JAVA面试题解惑系列(一)——类的初始化顺序-JAVA程序员JAVA工程师面试必看

JAVA面试题解惑系列(一)——类的初始化顺序-JAVA程序员JAVA工程师面试必看

-JAVA程序员JAVA工程师面试必看JAVA面试题解惑系列(一)——类的初始化顺序关键字: java 面试题初始化作者:臧圩人(zangweiren)网址:>>>转载请注明出处!<<<大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果。

这实际上是在考查我们对于继承情况下类的初始化顺序的了解。

我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器。

我们也可以通过下面的测试代码来验证这一点:Java代码1.publicclassInitialOrderTest{2..完全错误..yang_rabbit 2008-07-01学习了,谢谢naff 2008-07-01good!!!!andy54321 2008-06-30好的,清晰明了,明白了许多zzg2008 2008-06-30讲解得很清晰很透彻,学习了。

huyuhong001 2008-06-30可以不错jylovejava 2008-06-30不错!学习了InnocentBoy 2008-06-30有噱头,不实用。

个人感觉。

jike0616 2008-06-30哇!又学习了。

感谢LZlovinchan 2008-06-29总结得很好,重新认识了很多。

-JAVA程序员JAVA工程师面试必看。

Java类初始化过程

Java类初始化过程

Java类初始化过程一、java类的初始化顺序(1)加载父类(以下序号相同,表明初始化是按代码从上到下的顺序来的)1.为父类的静态属性分配空间并赋于初值1.执行父类静态初始化块;(2)加载子类2.为子类的静态属性分配空间并赋于初值2.执行子类的静态的内容;(3)加载父类构造器3.初始化父类的非静态属性并赋于初值3.执行父类的非静态代码块;4.执行父类的构造方法;(4)加载子类构造器5.初始化子类的非静态属性并赋于初值5.执行子类的非静态代码块;6.执行子类的构造方法.总之一句话,静态代码块内容先执行(父先后子),接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。

二、静态变量和静态代码块的初始化顺序:谁在前面先初始化谁(这个也比较容易理解,初始化的时候,不可能跳着去初始化吧,比如说静态代码块在静态变量的前面,不可能先跳过静态代码块的初始化先去执行静态变量的初始化吧。

)===================================================================== 对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序是:(静态变量、静态初始化块)>(变量、初始化块)>构造器。

我们也可以通过下面的测试代码来验证这一点: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("构造器");}new InitialOrderTest();}}运行以上代码,我们会得到如下的输出结果:静态变量静态初始化块变量初始化块构造器这与上文中说的完全符合。

初始化面试题及答案

初始化面试题及答案

初始化面试题及答案1. 请解释什么是初始化(Initialization)?- 答案:初始化是程序运行时,为变量、对象等分配内存空间,并赋予初始值的过程。

在不同的编程语言中,初始化的方式和时机可能有所不同。

2. 在Java中,如何进行类的成员变量的初始化?- 答案:在Java中,类的成员变量可以通过以下方式进行初始化: - 直接在变量声明时赋予初始值。

- 使用构造器进行初始化。

- 使用初始化块,可以是静态的也可以是非静态的。

3. 静态初始化块与实例初始化块有什么区别?- 答案:静态初始化块用于初始化静态变量,它在类加载时执行一次;实例初始化块用于初始化实例变量,它在每次创建新对象时执行。

4. 什么是默认初始化?Java中的默认初始化值有哪些?- 答案:默认初始化是指在没有显式初始化的情况下,系统自动为变量赋予的初始值。

在Java中:- 整型(int)默认初始化为0。

- 浮点型(float和double)默认初始化为0.0。

- 字符型(char)默认初始化为0,即'\u0000'。

- 布尔型(boolean)没有默认值,必须显式初始化。

- 引用类型默认初始化为null。

5. 在C++中,构造函数的作用是什么?- 答案:在C++中,构造函数的主要作用是初始化对象的状态。

它在创建对象时自动调用,用于设置对象的初始值,分配资源等。

6. 什么是构造函数重载?构造函数重载的意义是什么?- 答案:构造函数重载是指一个类可以有多个同名的构造函数,只要它们的参数列表不同即可。

构造函数重载的意义在于允许创建同一类的不同对象时,可以提供不同的初始化方式。

7. 请解释C++中的拷贝构造函数及其作用。

- 答案:拷贝构造函数是C++中的一种特殊的构造函数,它接受一个同类型的对象作为参数,并使用该对象来初始化当前对象。

其作用是简化对象的复制操作,确保深拷贝的正确实现。

8. 什么是C++中的初始化列表?它有什么优点?- 答案:初始化列表是C++中用于初始化类成员的一种语法,其格式是在构造函数的参数列表后面使用冒号和花括号包围的列表。

java 类初始化加载方法

java 类初始化加载方法

java 类初始化加载方法在Java中,类的初始化过程包括加载、链接(验证、准备、解析)和初始化三个阶段。

以下是对这三个阶段的简单解释:1. 加载(Loading):这是类加载的第一个阶段,主要任务是加载类。

当一个类被加载时,Java虚拟机(JVM)首先会在当前已加载的类列表中查找该类。

如果列表中已经存在,那么JVM就会直接使用已经加载的类。

如果列表中不存在,JVM会先在文件系统或者JAR文件中找到类的字节码文件,并将这个文件读入到内存中,然后在内存中生成该类的`Class`对象。

2. 链接(Linking):这个阶段又可以分为三个步骤:验证、准备和解析。

验证:验证的主要目的是确保被加载的类文件的内容符合Java语言规范,不会危害JVM的安全运行。

验证过程会检查类文件的每一个部分,包括类的结构、符号引用等是否符合规范。

准备:准备阶段是为类的静态变量分配内存,并设置默认的初始值。

需要注意的是,这里的静态变量只包括那种没有指定初始值的变量,和常量(被final修饰的静态变量)。

解析:解析阶段是将符号引用转换为直接引用。

简单来说,符号引用就是一种描述目标对象的抽象地址或者名称的方式,而直接引用就是直接通过内存地址来访问目标对象。

3. 初始化(Initialization):这是类加载的最后一个阶段。

在这个阶段,JVM会对类的静态变量进行初始化,即执行类变量赋值操作和静态代码块的内容。

需要注意的是,初始化阶段是在首次使用到该类的时候进行的,如果类还没有初始化,就会进行初始化工作,如果已经初始化过了,那么就会跳过初始化阶段。

以上就是Java中类的初始化过程和步骤。

[java]类变量初始化顺序

[java]类变量初始化顺序

[java]类变量初始化顺序前⾔本博客旨在深⼊了解类变量的初始化,如果有分析错误的地⽅,希望得到各位⼤⽜的指正.类成员变量类的成员变量分为两种: 普通成员变量和静态成员变量普通成员变量 :它被存储在堆内存中,每个对象都有⾃⼰的⼀个变量静态成员变量 :使⽤static关键词修饰的成员变量,它被存储在静态⽅法区 ,该类的所有对象都共享这个变量成员变量的初始化类的成员变量初始化地点有三处:声明时初始化代码块中初始化构造器中初始化成员变量初始化顺序成员变量初始化顺序让我们来看下⾯的⼀段代码:CommonMemberVariableTest.java:public class CommonMemberVariableTest {public static void main(String ...agrs) {CommonMemberVariable commonMemberVariable = new CommonMemberVariable();}}class ParentCommonMemberVariable {private Variable1 parentVariable1 = new Variable1("parent v1 statement");private Variable1 parentVariable2 = new Variable1("parent v2 statement");private static Variable1 parentStaticVariable1 = new Variable1("static parent v1 statement");private static Variable1 parentStaticVariable2 = new Variable1("static parent v2 statement");{parentVariable1 = new Variable1("parent v1 code block");}static {parentStaticVariable1 = new Variable1("static parent v1 code block");}public ParentCommonMemberVariable() {parentVariable1 = new Variable1("parent v1 constructor");}}class CommonMemberVariable extends ParentCommonMemberVariable {private Variable1 variable1 = new Variable1("v1 statement");private Variable1 variable2 = new Variable1("v2 statement");private static Variable1 staticVariable1 = new Variable1("static v1 statement");private static Variable1 staticVariable2 = new Variable1("static v2 statement");{variable1 = new Variable1("v1 code block");}static {staticVariable1 = new Variable1("static v1 code block");}public CommonMemberVariable() {variable1 = new Variable1("v1 constructor");}}class Variable1 {public Variable1(String info) {System.out.println(info);}上⾯代码的执⾏结果如下:static parent v1 statementstatic parent v2 statementstatic parent v1 code blockstatic v1 statementstatic v2 statementstatic v1 code blockparent v1 statementparent v2 statementparent v1 code blockparent v1 constructorv1 statementv2 statementv1 code blockv1 constructor结论:当我们只看variable1这个成员变量时,从打印可以发现,普通成员变量的初始化执⾏顺序是声明时初始化 -> 代码块中初始化 ->构造器中初始化当我们的类种有多个普通成员变量时,那么多个普通成员变量的初始化顺序是按照从上往下的顺序进⾏初始化如果我们只看⼦类或者⽗类的普通成员变量和静态成员变量,则会发现静态成员变量的初始化要先于普通成员变量,并且静态成员变量的初始化于普通成员变量的初始化顺序保持⼀致当我们的类种有继承关系时,那初始化的顺序为⽗类静态变量声明时 -> ⽗类静态代码块 -> ⼦类静态变量声明时 -> ⼦类静态代码块 -> ⽗类普通成员变量声明时 ->⽗类代码块 -> ⽗类构造器 -> ⼦类普通成员变量声明时 -> ⼦类代码块 -> ⼦类构造器。

Java继承结构中类的初始化

Java继承结构中类的初始化

Java继承结构中类的初始化Java继承结构中类的初始化Java继承结构中类的初始化的'代码是怎样的你知道吗?你对Java 继承结构中类的初始化了解吗?下面是店铺为大家带来的关于Java继承结构中类的初始化的知识,欢迎阅读。

Java继承结构中类的初始化package nie.test.extend;/** 子构造子的初始化过程:* @author dotjar* 1.父static域* 2.父static块* 3.子static域* 4.子static块* 5.父普通域* 6.父普通块{}* 7.父构造子* 8.子普通域* 9.子普通块{}* 10.子构造子*/public class Test {public static void main(String[] args) {new Son("s");}}class Father {static protected String s = "father_static_property_string"; //1 protected String b = "father_normal_property_string"; //5static {s = "o"; //2System.out.print("d");System.out.print(s);}{b="r"; //6System.out.print("a");System.out.print(b);}Father() {this("@");System.out.print("1"); //8}Father(String s) {System.out.print(s); //7}}class Son extends Father {public static String s = "son_static_property_string"; //3 public String b = "son_normal_property_string"; //9 static {s = "j"; //4System.out.print("t");System.out.print(s);}{b = "3"; //10System.out.print("6");System.out.print(b);}Son() {System.out.print("."); //11}Son(String s) {this();System.out.print("com"); //12 }}【Java继承结构中类的初始化】。

java类的初始化和对象的创建顺序

java类的初始化和对象的创建顺序

java类的初始化和对象的创建顺序学习java编程思想--类的初始化p146类的加载顺序* 1加载器启动找到 xxx.class⽂件,通过extends关键字寻找基类,先加载基类* 2类初始化先初始化static成员变量和static--->* 2先初始化⽗类的static成员变量和static* 3再初始化本类的static成员变量和static* 类加载之后,对象创建开始* 1先加载⽗类的⾮静态成员变量(静态成员变量在类初始化的时候已经加载,⾮静态成员变量要随对象的创建⽽初始化)* 2先加载⽗类的构造函数* 3再加载本类的⾮静态成员变量* 4再加载本类的构造函数*总体:* -->表⽰顺序* ⽗类-->⼦类* 静态-->⾮静态* 类-->对象* static随类的加载⽽加载* ⾮static成员变量随对象的创建⽽加载* 成员变量先于构造器加载1package com.test.java.classs;23/**4 * Created by Administrator on 2015/12/8.5 * 类的加载顺序6 * 1加载器启动找到 xxx.class⽂件,通过extends关键字寻找基类,先加载基类7 * 2类初始化先初始化static成员变量和static--->8 * 2先初始化⽗类的static成员变量和static9 * 3再初始化本类的static成员变量和static10 * 类加载之后,对象创建开始加载11 * 1先加载⽗类的⾮静态成员变量(静态成员变量在类初始化的时候已经加载,⾮静态成员变量要随对象的创建⽽初始化)12 * 2先加载⽗类的构造函数13 * 3再加载本类的⾮静态成员变量14 * 4再加载本类的构造函数15 *16 * 总体:17 * -->表⽰顺序18 * ⽗类-->⼦类19 * 静态-->⾮静态20 * 类-->对象21 * static随类的加载⽽加载22 * ⾮static成员变量随对象的创建⽽加载23 * 成员变量先于构造器加载24 *25*/26public class ClassLoadOrder extends Father{27//2⽗类的static成员变量加载完之后开始加载⼦类的static域28private static int k = printInt("child static k initialized");29//5 ⼦类的⾮静态成员变量初始化30private int m = printInt("child ⾮static 变量加载");3132//⼦类的构造器加载33public ClassLoadOrder() {34 System.out.println("child constructor initialized");35 System.out.println("k="+k);36 System.out.println("j="+j);37 }3839static {40 System.out.println("child static initialized");41 }42static int printInt2(){43 System.out.println("child static function initialized");44return 50;45 }4647public static void main(String[] args) {48 ClassLoadOrder c = new ClassLoadOrder();49 }50}5152class Father{53private int i=9;54protected int j;55//4 ⽗类构造器加载56 Father(){57 System.out.println("father constructor initialized");58 System.out.println("i="+i+",j="+j);59 j=39;60 }61//3 对象创建时,先初始化⽗类的⾮静态成员变量62int n = printInt("father ⾮static变量加载");63//1先加载⽗类的static域64static {65 System.out.println("father static initialized");66 }67//168private static int x1 = printInt("father static .x1 initialized"); 69static int printInt(String s ){70 System.out.println(s);71return 47;72 }73 }结果:father static initializedfather static .x1 initializedchild static k initializedchild static initializedfather ⾮static变量加载father constructor initializedi=9,j=0child ⾮static 变量加载child constructor initializedk=47j=39。

java继承中的初始化顺序

java继承中的初始化顺序

java继承中的初始化顺序初始化顺序:⽗类的静态变量-->⽗类的静态代码块-->⼦类的静态变量-->⼦类的静态代码快-->⽗类的⾮静态变量(⽗类的⾮静态代码块)-->⽗类的构造函数-->⼦类的⾮静态变量(⼦类的⾮静态代码块)-->⼦类的构造函数值得注意的是:⽗类的⾮静态变量(⽗类的⾮静态代码块)是同⼀级的,看哪个部分写在类的最前⾯谁就先被执⾏,⼦类的⾮静态变量(⼦类的⾮静态代码块)也是⼀样。

###验证代码:package com.hts.test;public class Test {public static void main(String[] args) {Child c=new Child();}}class Parent {public static PrintMessage a=new PrintMessage("⽗类静态成员被初始化");private PrintMessage b=new PrintMessage("⽗类⾮静态成员被初始化");static{System.out.println("⽗类的静态代码块被执⾏");}{System.out.println("⽗类的⾮静态代码块被执⾏");}public Parent(){System.out.println("⽗类的构造⽅法被执⾏");}}class Child extends Parent{public static PrintMessage a1=new PrintMessage("⼦类静态成员被初始化");private PrintMessage b1=new PrintMessage("⼦类⾮静态成员被初始化");static {System.out.println("⼦类的静态代码块被执⾏");}{System.out.println("⼦类的⾮静态代码块被执⾏");}public Child(){System.out.println("⼦类的构造函数被执⾏");}}class PrintMessage{public PrintMessage(String mes){System.out.println(mes);}}输出结果:。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

-JAVA程序员JAVA工程师面试必看JAVA面试题解惑系列(一)——类的初始化顺序关键字: java 面试题初始化作者:臧圩人(zangweiren)网址:>>>转载请注明出处!<<<大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果。

这实际上是在考查我们对于继承情况下类的初始化顺序的了解。

我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是(静态变量、静态初始化块)>(变量、初始化块)>构造器。

我们也可以通过下面的测试代码来验证这一点:Java代码1.public class InitialOrderTest {2.3. // 静态变量4. public static String staticField = "静态变量";5. // 变量6. public String field = "变量";7.8. // 静态初始化块9. static {10. System.out.println(staticField);11. System.out.println("静态初始化块");12. }13.14. // 初始化块15. {16. System.out.println(field);17. System.out.println("初始化块");18. }19.20. // 构造器21. public InitialOrderTest() {22. System.out.println("构造器");23. }24.25. public static void main(String[] args) {26. new InitialOrderTest();27. }28.}运行以上代码,我们会得到如下的输出结果:1.静态变量2.静态初始化块3.变量4.初始化块5.构造器这与上文中说的完全符合。

那么对于继承情况下又会怎样呢?我们仍然以一段测试代码来获取最终结果:Java代码1.class Parent {2. // 静态变量3. public static String p_StaticField = "父类--静态变量";4. // 变量5. public String p_Field = "父类--变量";6.7. // 静态初始化块8. static {9. System.out.println(p_StaticField);10. System.out.println("父类--静态初始化块");11. }12.13. // 初始化块14. {15. System.out.println(p_Field);16. System.out.println("父类--初始化块");17. }18.19. // 构造器20. public Parent() {21. System.out.println("父类--构造器");22. }23.}24.25.public class SubClass extends Parent {26. // 静态变量27. public static String s_StaticField = "子类--静态变量";28. // 变量29. public String s_Field = "子类--变量";30. // 静态初始化块31. static {32. System.out.println(s_StaticField);33. System.out.println("子类--静态初始化块");34. }35. // 初始化块36. {37. System.out.println(s_Field);38. System.out.println("子类--初始化块");39. }40.41. // 构造器42. public SubClass() {43. System.out.println("子类--构造器");44. }45.46. // 程序入口47. public static void main(String[] args) {48. new SubClass();49. }50.}运行一下上面的代码,结果马上呈现在我们的眼前:1.父类--静态变量2.父类--静态初始化块3.子类--静态变量4.子类--静态初始化块5.父类--变量6.父类--初始化块7.父类--构造器8.子类--变量9.子类--初始化块10.子类--构造器现在,结果已经不言自明了。

大家可能会注意到一点,那就是,并不是父类完全初始化完毕后才进行子类的初始化,实际上子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。

那么对于静态变量和静态初始化块之间、变量和初始化块之间的先后顺序又是怎样呢?是否静态变量总是先于静态初始化块,变量总是先于初始化块就被初始化了呢?实际上这取决于它们在类中出现的先后顺序。

我们以静态变量和静态初始化块为例来进行说明。

同样,我们还是写一个类来进行测试:Java代码1.public class TestOrder {2. // 静态变量3. public static TestA a = new TestA();4.5. // 静态初始化块6. static {7. System.out.println("静态初始化块");8. }9.10. // 静态变量11. public static TestB b = new TestB();12.13. public static void main(String[] args) {14. new TestOrder();15. }16.}17.18.class TestA {19. public TestA() {20. System.out.println("Test--A");21. }22.}23.24.class TestB {25. public TestB() {26. System.out.println("Test--B");27. }28.}运行上面的代码,会得到如下的结果:1.Test--A2.静态初始化块3.Test--B大家可以随意改变变量a、变量b以及静态初始化块的前后位置,就会发现输出结果随着它们在类中出现的前后顺序而改变,这就说明静态变量和静态初始化块是依照他们在类中的定义顺序进行初始化的。

同样,变量和初始化块也遵循这个规律。

了解了继承情况下类的初始化顺序之后,如何判断最终输出结果就迎刃而解了。

∙10:13∙浏览 (4106)∙评论 (41)∙分类: JAVA面试题解惑系列∙收藏∙相关推荐评论zm2693450 2008-07-14好贴,顶起来臧圩人 2008-07-08回复狂放不羁:总结的很好,赞一个狂放不羁 2008-07-08静态代码为什么先于非静态代码这是因为静态代码是在类加载完毕后执行的,而加载类的顺序是先父类后子类,所以静态代码的执行是先执行父类的,然后执行子类的。

对于非静态变量以及实例初始化块都是在构造函数里的代码执行前执行。

所以静态代码是在类加载后执行,而实例代码是在构造函数执行前执行。

但是当我们显示控制类加载的时候情况有点变化,显示加载可以有关两种方法:第一种:利用forName方法当我们查API文档就会发现forName方法有两种形式。

分别如下:public static Class<?> forName(String className)throws ClassNotFoundExceptionpublic static Class<?> forName(String name,boolean initialize,ClassLoader loader)throws ClassNotFoundException第二个方法值得注意的就是第二个参数boolean initialize,如果我们把这个参数设置为false,那么当我们加载完类后就不会执行静态代码和静态的初始化动作。

只有当我们new一个对象的时候才会初始化。

而第三个参数是用来指明类的加载器的。

如果查看ng.Class类的源代码,上述两种方法最终都会调用Class类中的私有的native方法forName0(),此方法的声明如下:private static native Class forName0(String name, boolean init , ClassLoader loader)throws ClassNotFoundException;所以当我们调用Class.forName(name )时,其实是在方法内部调用了:forName0(name, true, ClassLoader.getCallerClassLoader());当我们调用Class.forName(name, initialize, loader )的时候,实际上此方法内部调用了:forName0(name, initialize, loader);第二种:利用Class对象获取的ClassLoader装载。

此方法也是在实例化时才执行静态代码的执行。

综上所述可以总结如下:1 对于隐式的加载(new一个对象和调用类的静态方法),静态代码是在类加载后立刻执行,而对于显示加载(第一种是用ng.Class的forName(String str)方法,第二种是用ng.ClassLoader的loadClass())就如同我上面所说,加载过程是可以由我们来控制的。

2 实例化代码执行是载构造函数执行之前,涉及到继承时,父类的构造函数执行之前执行父类里的实例化代码,子类的构造函数执行之前执行子类的实例化代码。

所以这样可以保证子类中用到的变量都是已经经过父类初始化的,从而保证了初始化的正确性。

呵呵,这些是我学习J2SE的时候总结的,今天和大家分享。

臧圩人 2008-07-06回复Unmi:你的建议很好学习任何东西都有一个由浅入深的过程,能够掌握的广泛和深入固然好,不过有时候够用也是一个不错的标准Unmi 2008-07-06实际上你理解了内存中的对象模型就用不着这样的长篇累椟,这也是java人相比与c++人员的一种缺陷,逃避了对内存,指针的感性理解,有些问题,譬如,转型,以及如上的类的初始化顺序反而把自己搞糊涂了。

相关文档
最新文档