" final"的初始化实例变量

时间:2014-05-14 17:42:01

标签: java final class-instance-variables

我想了解各种情况下类实例的初始化。
在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

3 个答案:

答案 0 :(得分:2)

这个

final int e = a;

constant variableconstant 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

首先要记住我已经为ParentChild类编写了初始化块,这是在构造函数之前调用的。

现在,如果您可以从创建Child对象的输出中看到第一个Parent类被加载到内存中,那么您在meth构造函数Parent方法>这将调用meth类的Child方法,但Child此时初始化块和Child的构造函数未被调用这意味着此时b未初始化为30,而是int默认值0,与e变量相同。