登陆

章鱼世界官网-大伽说这道JVM题一般人都 会做错,那你是不是一般人呢?

admin 2019-05-18 276人围观 ,发现0个评论


有关Java虚拟机类加载机制相关的文章一搜一大把,笔者这儿也不用再赘述一遍了。笔者这儿捞出一道code题要各位大佬来把玩把玩,假如你一眼就看出了端倪,那么祝贺你,你能够下山了:

public class StaticTest
{
public static void main(String[] args)
{
staticFunction();
}
static StaticTest st = new StaticTest();
static
{
System.out.println("1");
}
{
System.ou章鱼世界官网-大伽说这道JVM题一般人都 会做错,那你是不是一般人呢?t.println("2");
}
StaticTest()
{
System.out.println("3");
System.out.println("a="+a+",b="+b);
}
public static void staticFunction(){
System.out.println("4");
}
i章鱼世界官网-大伽说这道JVM题一般人都 会做错,那你是不是一般人呢?nt a=110;
s在线测速tatic int b =112;
}

问题:请问这段程序的输出是什么?一般关于这类问题,小伙伴们脑海中必定浮现出这样的常识点:

Java中赋值次序:
  • 父类的静态变量赋值
  • 本身的静态变量赋值
  • 父类成员变量赋值和父类块赋值
  • 父类结构函数赋值
  • 本身成员变量赋值和本身块赋值
  • 本身章鱼世界官网-大伽说这道JVM题一般人都 会做错,那你是不是一般人呢?结构函数赋值

依照这个理论输出是什么呢?答案输出:1 4,这样正确嚒?必定不正确啦,这儿不是说上面的规矩不正确,而是说不能简略的套用这个规矩。 正确的答案是:

2
3
a=110,b=0
1
4

有没有答对呢?这儿首要的点之一:实例初始化不一定要在类初始化完毕之后才开端初始化。 类的生命周期是:加载->验证->预备章鱼世界官网-大伽说这道JVM题一般人都 会做错,那你是不是一般人呢?->解析->初始化->运用->卸载,只要在预备阶段和初始化阶段才会触及类变量的初始化和赋值,因而只针对这两个阶段进行剖析;

类的预备阶段需求做是为类变量分配内存并设置默认值,因而类变量st为null、b为0;(需求留意的是假如类变量是final,编译时javac将会为value生成ConstantValue特点,在预备阶段虚拟机就会依据ConstantValue的设置将变量设置为指定的值,假如这儿这么界说:static final int b=112,那么在预备阶段b的值便是112,而不再是0了。)

类的初始化阶段需求做的是履行类结构器(类结构器是编译器搜集一切静态句子块和类变量的赋值句子按句子在源码中的次序兼并生成类结构器,目标的结构办法是(),类的结构办法是(),能够在仓库信息中看到),因而先履行第一条静态变量的赋值句子即st = new StaticTest (),此刻会进行目标的初始化,目标的初始化是先初始化成员变量再履行结构办法,因而打印2->设置a为110->履行结构办法(打印3,此刻a现已赋值为110,可是b仅仅设置了默认值0,并未完结赋值动作),等目标的初始化完结后持续履行之前的类结构器的句子,接下来就不具体说了,依照句子在源码中的次序履行即可。


这儿面还牵涉到一个冷常识,便是在嵌套初始化时有一个特别的逻辑。特别是内嵌的这个变量恰好是个静态成员,并且是本类的实例。 这会导致一个风趣的现象:“实例初始化居然出现在静态初章鱼世界官网-大伽说这道JVM题一般人都 会做错,那你是不是一般人呢?始化之前”。 其实并没有提早,你要知道java记载初始化与否的机遇。看一个简化的代码,把关键问题解说清楚:

public class Test {
public 章鱼世界官网-大伽说这道JVM题一般人都 会做错,那你是不是一般人呢?static void main(String[] args) {
func();
}
static Test st = new Test();
static void func(){}
}

依据上面的代码,有以下进程:

  1. 首先在履行此段代码时,首先由main办法的调用触发静态初始化。
  2. 在初始化Test 类的静态部分时,遇到st这个成员。
  3. 但恰巧这个变量引证的是本类的实例。
  4. 那么问题来了,此刻静态初始化进程还没完结就要初始化实例部分了。是这样么?
  5. 从人的视点是的。但从java的视点,一旦开端初始化静态部分,不管是否完结,后续都不会再从头触发静态初始化流程了。
  6. 因而在实例化st变量时,实际上是把实例初始化嵌入到了静态初始化流程中,并且在楼主的问题中,嵌入到了静态初始化的开始方位。这就导致了实例初始化彻底至于静态初始化之前。这也是导致a有值b没值的原因。
  7. 最终再考虑到文本次序,成果就清楚明了了。

今日就到这儿啦,喜爱编程的小伙伴能够重视我哦!有学习方面的问题能够私信回复:学习!

  • 章鱼世界官网-北京新发地:猪肉批发价回落 下一年有望根本康复到正常水平
  • A股三大股指全线上涨 沪指重回2900点
  • 请关注微信公众号
    微信二维码
    不容错过
    Powered By Z-BlogPHP