不可预测的初始化块行为

huangapple go评论92阅读模式
英文:

Unpredictable behaviour of an initializer block

问题

public class Ex14 {
    static String strDef = "在定义的地方";
    static String strBlock;
    { strBlock = "在一个块中"; }
    
    public static void main(String[] args) {
        System.out.println(Ex14.strDef);
        System.out.println(Ex14.strBlock);
        Ex14 test = new Ex14();
        System.out.println(test.strBlock);
        System.out.println(Ex14.strBlock);
    }
}

结果:

$ java Ex14
在定义的地方
null
在一个块中
在一个块中

如果我将块与注释部分互换,两个语句都会被打印出来。换句话说,我无法理解发生了什么。

问题:

  1. 在初始化块内部,该变量是非静态的。如果它没有与静态声明混在一起,为什么编译器甚至没有警告我?

  2. 当创建一个实例时,strBlock 不再为 null。我无法理解为什么?

  3. 无论如何,我在这里什么都无法理解。请问,你能否在某种程度上进行解释?

英文:
public class Ex14 {
	static String strDef = "At the point of definition";
	static String strBlock;
	{ strBlock = "In a block";}
		
	public static void main (String [] args){		
		System.out.println(Ex14.strDef);
		System.out.println(Ex14.strBlock);
		Ex14 test = new Ex14();
		System.out.println(test.strBlock);
		System.out.println(Ex14.strBlock);
	}
	
}

Result:

$ java Ex14
At the point of definition
null
In a block
In a block

If I switch the block with the commented one, both statements are printed. In other words, I just

Well, I can't catch what is going on here.

Questions:

  1. Inside the initializer block the variable is non-static. If it is
    not anyhow mixed with that static declaration, why the compiler
    didn't even warn me?

  2. When an instance was created, strBlock is not null anymore. I can't
    catch why?

  3. Anyway, I can't understand anything here. Please, could you clarify
    it somehow?

答案1

得分: 2

Sure, here's the translated content:

  1. 在初始化块内,变量是非静态的。如果它与静态声明没有混合在一起,为什么编译器甚至没有警告我呢?

不,变量仍然是 static 的。你只是给静态变量赋了一个新值。

  1. 当实例被创建时,strBlock 不再是 null。我无法理解为什么?

实例初始化块被内联到构造函数中,在隐式或显式调用 super(...) 之间以及其余部分之间。你这里的情况等同于:

public class Ex14 {
    static String strDef = "在定义的时候";
    static String strBlock;

    public Ex14() {  // 默认构造函数。
      super(); // 隐式调用超类构造函数。

      // 内联的实例初始化块。
      Ex14.strBlock = "在块中";
      
      // 构造函数的其余部分(对于默认构造函数没有)。
    }

    public static void main (String [] args){ 
      // ...
    }
 }

因此,在创建实例之前,Ex14.strBlock = "在块中"; 这个语句还没有执行,所以它的值是 null;在创建实例之后(因此执行构造函数),Ex14.strBlock 已经被重新赋值。

英文:

> 1. Inside the initializer block the variable is non-static. If it is not anyhow mixed with that static declaration, why the compiler didn't even warn me?

No, the variable is still static. You're just assigning a new value to the static variable.

> 2. When an instance was created, strBlock is not null anymore. I can't catch why?

Instance initializers are inlined into the constructor, in between an (implicit or explicit) call to super(...) and the rest of the body. What you have here is equivalent to:

public class Ex14 {
    static String strDef = "At the point of definition";
    static String strBlock;

    public Ex14() {  // Default constructor.
      super(); // Implicit super constructor invocation.

      // Inlined instance initializer.
      Ex14.strBlock = "In a block";
      
      // Rest of the constructor body (there is none for a default ctor).
    }

    public static void main (String [] args){ 
      // ...
    }
 }

So, before you create an instance, the Ex14.strBlock = "In a block"; statement hasn't executed, so its value is null; after you create an instance (and hence execute the constructor), Ex14.strBlock has been reassigned.

huangapple
  • 本文由 发表于 2020年4月8日 23:40:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/61104577.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定