java成员变量在什么时候赋值的?

2023-05-27 0 713

题主的难题槽点颇多…

从Java SE 6已经开始是这种的:

public class MyClass { private int a = 1; // field declaration with initializer { // instance initializer 1 a = 2; } public MyClass() { // constructor a = 4; } { // instance initializer 2 a = 3; } }

那个MyClass的内部结构器从Java词汇微观看是public MyClass() { … }的部份。但是对JVM而言大部份示例调用姿势都要搜集到“特定的示例调用方式”(名叫“<init>”,文本相关联大部份示例调用器+内部结构器)里,因此下面的标识符从JVM的角度观察会是这种:

public class MyClass { private int a; public void <init>() { // implicit superclass constructor call super(); // field initializer a = 1; // instance initializer 1 a = 2; // instance initializer 2 a = 3; // explicit constructor a = 4; } }

那个合成的<init>()V里,先是内部结构器里隐式或显式的super()调用,然后是按标识符顺序把示例调用姿势(包括示例字段调用与匿名的示例调用器)搜集起来,然后是内部结构器自身的文本。

Java词汇规范里对内部结构器中super()调用的位置的限制其实颇为鸡肋。一来可以通过上述方式通过写字段调用或示例调用器来在super()前执行标识符,二来就算不用它们而只用普通的内部结构器也还是可以在super()前执行标识符,只要super()可以接受至少一个参数——做法如下:

public class Derived extends Base { public Derived() { super(foo()); // assuming theres a Base(int) constructor System.out.println(“Derived ctor”); } private int foo() { System.out.println(“foo!”); // arbitrary side effect return 42; } }

只要基类有接受至少一个参数的内部结构器,子类的内部结构器在调用super()时就可以调用任意方式去提供那个参数的值,于是就可以在真的调用super()前产生任意的副作用了。

题主难题说:

内部结构器的目的是分配示例对象的内存空间

这是错误的。Java词汇里,new表达式总体负责两个姿势:

分配对象空间并对其做默认调用。默认调用会将对象的大部份核心成员字段设到其类型相关联的默认值(零值)。调用对象

其中内部结构器只负责第2点,第1点是包含在new表达式里的语义。

相关传送门:

如何理解《Java编程思想》描述的“即使没有显式地使用static关键字,内部结构器实际上也是静态方式”? – RednaxelaFX 的回答

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务