java中的静态代码块、代码块、构造器的执行顺序是怎样呢,这三者有什么作用呢
展开全部
还是不得不拿出<clinit>和<init>说事了。以下拿类T作为讲解的对象类型吧:
class T{
private static final String msg = "this is a test class!";
private static int version = 1;
static{
version = 2;
desc = "class T";
}
private static String desc = “T is a test Class”;
private int age = 2;
{
age = 10;
name = "panda";
}
public T(){
age = 12;
name = "foxli";
}
private String name = "micky";
}
类T,存在静态域version和desc,实例域age和name。
类中,存在静态代码块static{}以及实例化代码块{}和默认的构造方法。
------------------------------------------------------------------------------------------------------------
先来说一下类型初始化方法<clinit>:
JVM通过Classload进行类型加载时,如果在加载时需要进行类型初始化操作时,则会调用类型的初始化方法。类型初始化方法主要是对static变量进行初始化操作,对static域和static代码块初始化的逻辑全部封装在<clinit>方法中。
java.lang.Class.forName(String name, boolean initialize,ClassLoader loader),其中第二个参数就是是否需要初始化。
Java类型初始化过程中对static变量的初始化操作依赖于static域和static代码块的前后关系,static域与static代码块声明的位置关系会导致java编译器生成<clinit>方法打字节码。
由上例子,T类型的类型初始化方法<clinit>最后编译出来的字节码顺序大概是这样的:
T.<clinit>{
private static int version;
private static String desc;
version = 1;
version = 2;
desc = "class T";
desc = "T is a test Class";
}
类型的初始化方法<clinit>只在该类型被加载时才执行,且只执行一次。
-------------------------------------------------------------------------------------------------------------
接下来说一下对象实例化方法<init>:
Java对象在被创建时,会进行实例化操作。该部分操作封装在<init>方法中,并且子类的<init>方法中会首先对父类<init>方法的调用。
Java对象实例化过程中对实例域的初始化赋值操作全部在<init>方法中进行,<init>方法显式的调用父类的<init>方法,实例域的声明以及实例初始化语句块同样的位置关系会影响编译器生成的<init>方法的字节码顺序,<init>方法以构造方法作为结束。
由上例子,T对象的对象实例化方法<init>最后编译出来的字节码顺序大概是这样的:
T.<init>{
int age;
String name;
this.age = 2;
this.age = 10;
this.name = "panda";
this.name = "micky";
this.age = 12;
this.name = "foxli";
}
对象实例化方法<init>以构造方法作为结束。当前并没有考虑存在父类的情况,如果存在,<init>方法首先会调用父类的<init>方法。
-------------------------------------------------------------------------------------------------------------
PS:这里面的msg称为编译时常量,他不再<clinit>方法中出现。
其中<clinit>方法在javap命令中没有显示,javap输出的static{}就是<clinit>方法。
class T{
private static final String msg = "this is a test class!";
private static int version = 1;
static{
version = 2;
desc = "class T";
}
private static String desc = “T is a test Class”;
private int age = 2;
{
age = 10;
name = "panda";
}
public T(){
age = 12;
name = "foxli";
}
private String name = "micky";
}
类T,存在静态域version和desc,实例域age和name。
类中,存在静态代码块static{}以及实例化代码块{}和默认的构造方法。
------------------------------------------------------------------------------------------------------------
先来说一下类型初始化方法<clinit>:
JVM通过Classload进行类型加载时,如果在加载时需要进行类型初始化操作时,则会调用类型的初始化方法。类型初始化方法主要是对static变量进行初始化操作,对static域和static代码块初始化的逻辑全部封装在<clinit>方法中。
java.lang.Class.forName(String name, boolean initialize,ClassLoader loader),其中第二个参数就是是否需要初始化。
Java类型初始化过程中对static变量的初始化操作依赖于static域和static代码块的前后关系,static域与static代码块声明的位置关系会导致java编译器生成<clinit>方法打字节码。
由上例子,T类型的类型初始化方法<clinit>最后编译出来的字节码顺序大概是这样的:
T.<clinit>{
private static int version;
private static String desc;
version = 1;
version = 2;
desc = "class T";
desc = "T is a test Class";
}
类型的初始化方法<clinit>只在该类型被加载时才执行,且只执行一次。
-------------------------------------------------------------------------------------------------------------
接下来说一下对象实例化方法<init>:
Java对象在被创建时,会进行实例化操作。该部分操作封装在<init>方法中,并且子类的<init>方法中会首先对父类<init>方法的调用。
Java对象实例化过程中对实例域的初始化赋值操作全部在<init>方法中进行,<init>方法显式的调用父类的<init>方法,实例域的声明以及实例初始化语句块同样的位置关系会影响编译器生成的<init>方法的字节码顺序,<init>方法以构造方法作为结束。
由上例子,T对象的对象实例化方法<init>最后编译出来的字节码顺序大概是这样的:
T.<init>{
int age;
String name;
this.age = 2;
this.age = 10;
this.name = "panda";
this.name = "micky";
this.age = 12;
this.name = "foxli";
}
对象实例化方法<init>以构造方法作为结束。当前并没有考虑存在父类的情况,如果存在,<init>方法首先会调用父类的<init>方法。
-------------------------------------------------------------------------------------------------------------
PS:这里面的msg称为编译时常量,他不再<clinit>方法中出现。
其中<clinit>方法在javap命令中没有显示,javap输出的static{}就是<clinit>方法。
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
静态代码块->构造器->代码块
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询