在构造函数中初始化静态final字段

时间:2011-02-23 16:28:46

标签: java static constructor final

public class A 
{    
    private static final int x;

    public A() 
    {
        x = 5;
    }
}
  • final表示变量只能分配一次(在构造函数中)。
  • static表示它是一个类实例。

我不明白为什么这是禁止的。这些关键词在哪里相互干扰?

8 个答案:

答案 0 :(得分:171)

每次创建类的实例时都会调用构造函数。因此,上面的代码意味着每次创建实例时都会重新初始化x的值。但是因为变量被声明为final(和static),所以你只能这样做

class A {    
    private static final int x;

    static {
        x = 5;
    }
}

但是,如果你删除静态,你可以这样做:

class A {    
    private final int x;

    public A() {
        x = 5;
    }
}

或者这个:

class A {    
    private final int x;

    {
        x = 5;
    }
}

答案 1 :(得分:16)

在加载类时初始化静态最终变量。构造函数可以稍后调用,或者根本不调用。此外,构造函数将被多次调用(每个新对象),因此该字段不再是最终的。

如果您需要自定义逻辑来初始化静态最终字段,请将其放在静态块中

答案 2 :(得分:6)

考虑第二次实例化对象时会发生什么。它试图将它设置为AGAIN,这是一个静态的决赛明确禁止的。它只能为整个类设置一次,而不是实例。

您应该在声明时设置值

private static final x=5;

如果您需要额外的逻辑或更复杂的实例化,可以在静态初始化程序块中完成。

答案 3 :(得分:5)

static表示该变量在应用程序上是唯一的。 final表示只应设置一次。

如果在构造函数中设置它,则允许多次设置变量。

因此,您应该直接初始化它或提出一个静态方法来初始化它。

答案 4 :(得分:3)

最终并不意味着必须在构造函数中初始化。 通常这就是做的事情:

 private static final int x = 5;

static 代替表示该变量将通过该类的多个实例共享。例如:

public class Car {
   static String name;
   public Car(String name) {
      this.name = name;
   }
}

...

Car a = new Car("Volkswagen");
System.out.println(a.name); // Produces Volkswagen

Car b = new Car("Mercedes");
System.out.println(b.name); // Produces Mercedes
System.out.println(a.name); // Produces Mercedes

答案 5 :(得分:2)

想一想。您可以使用您的代码执行此操作:

A a = new A();
A b = new A(); // Wrong... x is already initialised

初始化x的正确方法是:

public class A 
{    
    private static final int x = 5;
}

public class A 
{    
    private static final int x;

    static
    {
        x = 5;
    }
}

答案 6 :(得分:0)

methods: {
    getLog() {


        this.users.forEach(element => {

            element.logs.forEach((log) => {

                this.Logs.push(log);

            })

        });

        var unfinished = this.Logs.filter((log) => {
            return log.finished == false;
        });

        console.log(unfinished);

        const input = [
            {id: 1, checkin_time: "2030-05-05 10:22:02"}, // 10 AM. 
            {id: 2, checkin_time: "2030-05-05 08:22:02"} // 8 AM.
        ]

        console.log(input);

        // Closest From Now.
        const closestFromNow = times => times.filter(x => Date.now() < new Date(x.checkin_time)).sort((a, b) => new Date(a.checkin_time)*1 - new Date(b.checkin_time)*1)[0]

        // Output.
        const output = closestFromNow(unfinished)
        const output2 = closestFromNow(input)

        // Proof.
        console.log(output) // Undefined
        console.log(output2) // ID 2. 8 AM.


    }
}

答案 7 :(得分:0)

静态

关键字static表示对象的成员(在这种情况下为字段)没有绑定到类的实例,而是对象的成员。如果静态成员是字段,则在加载类时对其进行初始化。

可通过类而不是通过实例进行访问(尽管后者并非不可能,但被认为是错误的形式),因此可以在没有构造函数运行的情况下进行访问。

最终

关键字final应用于对象的字段时,意味着只能被分配一次,并且在初始化期间必须被分配。

>

静态决赛

这两个关键字一起有效地定义了一个常数:它只能分配一次,必须分配,并且对于该类的所有实例都是相同的。

由于静态字段是在类加载期间初始化的,因此必须在声明时或在静态初始化程序块中对其进行初始化。

这意味着,当您到达构造函数时,它将已经被初始化,因为需要已经被初始化。

单人

如果您要查找只分配一次但多次读取的类成员,则您正在处理a singleton。单例模式通常用于访问共享资源。

该字段为静态字段,但不是最终字段;而是在访问该字段时,代码将检查它是否已经初始化,如果尚未初始化,则在此完成。请注意,在具有多个线程的环境中,您需要同步对该字段的访问,以避免在初始化时对其进行访问。