我想了解各种情况下类实例的初始化。
在JLS-7第12.5节中,没有提到最终实例变量的初始化方式和时间?有人可以指出我理解在实例变量被声明为final的情况下的行为吗?
public class Test {
public static void main(String args[]){
Child c1 = new Child();
}
}
class Parent{
final int a =30;
Parent(){
System.out.println("From super Contsrutor "+a);
meth();
}
void meth(){
System.out.println("From super");
}
}
class Child extends Parent{
final int e=super.a;
int b=30;
void meth(){
System.out.println("From Sub e=" +e+", b="+b);
}
}
按以下方式提供输出
From super Contsrutor 30
From Sub e=0,b=0
在哪里
public class Test {
public static void main(String args[]){
Child c1 = new Child();
}
}
class Parent{
final int a =30;
Parent(){
System.out.println("From super Contsrutor "+a);
meth();
}
void meth(){
System.out.println("From super");
}
}
class Child extends Parent{
final int e=a;
void meth(){
System.out.println("From Sub " +e);
}
}
将输出设为
From super Contsrutor 30
From Sub 30
答案 0 :(得分:2)
这个
final int e = a;
是constant variable,constant expression。在调用中
System.out.println("From Sub e=" +e+", b="+b);
编译器可以将e
的值替换为30
。
在
final int e = super.a;
变量e
不是常量变量,因为super.a
不是simple name,因此该值不能也不会被替换。
答案 1 :(得分:1)
第一段代码输出如下
From super Contsrutor 30
From Sub e=0,b=0
这是因为以下原因。
当我们new Child()
时,Child类的构造者开始执行
但它的第一个语句默认为super,因此它调用了父类constrctor
现在,父类constrcutor具有以下代码
父(){ System.out.println("来自超级Contsrutor" + a); 甲基(); }
所以这里的父类调用了meth()方法,它的调用者实际上是子类的子对象,所以它调用了子类的meth()方法。
现在当它从super constrcutor实际调用子类class()方法实际是子对象时 尚未创建,因此其变量尚未初始化,但我们正在打印a和b的值。
所以b在孩子建筑师完成执行后被分配之前得到0。
因此,如下所示更改您的第一段代码将提供所需的输出 即将meth()调用放在子构造函数中而不是父母构造函数中。
package com.kb.finalVariables;
public class Test {
public static void main(String args[]){
Child c1 = new Child();
}
}
class Parent{
final int a =30;
Parent(){
System.out.println("From super Contsrutor "+a);
// meth();
}
void meth(){
System.out.println("From super");
}
}
class Child extends Parent{
final int e=super.a;
int b=30;
public Child() {
meth();
}
void meth(){
System.out.println("From Sub e=" +e+", b="+b);
}
}
答案 2 :(得分:1)
让我们找出程序的流程,我在下面写了代码:
package com.test;
public class Test {
public static void main(String args[]) {
Child c1 = new Child();
}
}
class Parent {
final int a = 30;
static int count = 0;
{
System.out.println("Parent initialization block " + ++count);
}
Parent() {
System.out.println("Parent constructor " + ++count);
// System.out.println("From super Contsrutor " + a);
meth();
}
void meth() {
// System.out.println("From super");
System.out.println("Parent meth method " + ++count);
}
}
class Child extends Parent {
final int e = super.a;
int b = 30;
{
System.out.println("Child initialization block " + ++count);
}
public Child() {
System.out.println("Child constructor " + ++count);
}
void meth() {
System.out.println("Child meth method " + ++count);
// System.out.println("From Sub e=" + e + ", b=" + b);
}
}
<强>输出:强>
Parent initialization block 1
Parent constructor 2
Child meth method 3
Child initialization block 4
Child constructor 5
首先要记住我已经为Parent
和Child
类编写了初始化块,这是在构造函数之前调用的。
现在,如果您可以从创建Child
对象的输出中看到第一个Parent
类被加载到内存中,那么您在meth
构造函数Parent方法>这将调用meth
类的Child
方法,但Child
但此时初始化块和Child
的构造函数未被调用这意味着此时b未初始化为30,而是int
默认值0
,与e
变量相同。