简体   繁体   English

初始化“最终”实例变量

[英]Initialization of “final” instance variables

I would like to understand initialization of class instances in various cases.. 我想了解各种情况下类实例的初始化。
In JLS-7 Section 12.5, there was no mention of how and when final instance variables were initialized? 在JLS-7第12.5节中,没有提到最终实例变量的初始化方式和时间? Can some one point me reference to understand the behaviour in case of instance variables declared as final? 有人可以指出在实例变量被声明为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);
        }
    }

is giving Output as following 输出如下

From super Contsrutor 30
From Sub e=0,b=0

Where as 在哪里

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);
    }
}

is giving Output as 将输出作为

From super Contsrutor 30
From Sub 30

This 这个

final int e = a;

is a constant variable , a constant expression . 是一个常量变量 ,一个常量表达式 In the invocation 在调用中

System.out.println("From Sub e=" +e+", b="+b);

the compiler can replace the use of e with its value, 30 . 编译器可以用其值30替换e的使用。

In

final int e = super.a;

the variable e is not a constant variable, because super.a is not a simple name , and therefore the value cannot and will not be replaced. 变量e不是常量变量,因为super.a不是简单的名称 ,因此该值不能也不会被替换。

first piece of Code is giving the output as below 第一段代码输出如下

From super Contsrutor 30
From Sub e=0,b=0

This is because of below reason. 这是因为以下原因。

first thing when we do new Child() , the constrcutor of Child class starts execution 当我们做new Child() ,Child类的构造者开始执行

but its first statement is super by default so it gives a call to parent class constrctor 但它的第一个语句默认为super,因此它会调用父类constrctor

now Parent class constrcutor has below code 现在父类constrcutor有下面的代码

Parent(){ System.out.println("From super Contsrutor "+a); Parent(){System.out.println(“来自超级Contsrutor”+ a); meth(); 甲基(); } }

so here parent class is calling meth() method and its caller is actually a subclass child's object so it calls child class meth() method. 所以这里的父类调用了meth()方法,它的调用者实际上是子类的子对象,因此它调用了子类的meth()方法。

now when it calls child class meth() method from super constrcutor actually child object is not yet created so its variables are not yet initialized but we are printing the values for both a and b. 现在当它从super constrcutor调用child class meth()方法时,实际上还没有创建子对象,所以它的变量尚未初始化,但我们正在打印a和b的值。

so b gets 0 before getting assigned after child constrcutor gets execution completed. 因此,在孩子建筑师完成执行后,b在获得分配之前得到0。

so changing your first piece of code like below will give desired output ie putting meth() call inside child constrctor rather than on parent constrcutor. 所以改变你的第一段代码就像下面那样会产生所需的输出,即将meth()调用放在子构造函数中,而不是父母constrcutor。

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);
    }
}

Lets find out the flow of the program, I have written below code for it: 让我们找出程序的流程,我在下面写了代码:

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);
    }
}

Output: 输出:

Parent initialization block 1
Parent constructor 2
Child meth method 3
Child initialization block 4
Child constructor 5

First of all remember I have written initialization block for Parent and Child class, which is called before constructor. 首先要记住我已经为ParentChild类编写了初始化块 ,它在构造函数之前调用。

Now if you can see from output on creation of Child object first Parent class is loaded into memory, then you have called meth method inside Parent constructor that will call meth method of Child class but Child but at this time initialization block and constructor of Child is not called that means at this time b is not initialized to 30 but to int default value 0 , same case with e variable. 现在,如果你可以从创造的输出看Child对象第一Parent类被加载到内存中,那么你就称为meth内部方法Parent构造函数,将调用meth的方法, Child ,但Child在这个时候初始化块和构造Child是没有调用 ,这意味着此时b未初始化为30但是对于int默认值0 ,与e变量的情况相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM