在声明最终变量后,需要立即给出最终变量值

时间:2012-04-25 01:43:57

标签: java variables instantiation final

是否可以在程序的其他任何位置为最终变量赋值?或者是否必须在创建时为其分配值?

class TestClass() {
//this won't compile but is it possible to assign str a value anywhere else in the program?
public static final String str;
}

3 个答案:

答案 0 :(得分:3)

如果值已经声明,则需要在构造函数中指定一个值(如果它不是静态的),如果是,则在静态初始化程序块中。设置值后,无法修改。

这样做:

public class FinalTest {
    private static final String CONSTANT;

    private final String value;

    static {
        CONSTANT = "Hello";
    }

    public static void main(String [] args) {
        FinalTest ft = ((args.length > 0) ? new FinalTest(args[0]) : new FinalTest(CONSTANT));
        System.out.println(ft);
    }

    public FinalTest(String value) {
        this.value = value;
    }

    public String toString() { return this.value; }
}

答案 1 :(得分:2)

本地变量

final 变量需要在访问之前为分配一个值。这意味着如果它从未分配过值从未访问过,编译器不会抱怨。

void foo() {
    final int a; // Never assigned, but never accessed either, so no problem
    final int b = 7;

    System.out.println("b is " + b);

    // System.out.println("a is " + a);
    // Uncommenting the above line would cause a compile error
}

静态字段

类似的逻辑适用于final 静态字段,除非它假设它们将在某个时刻被访问,因此必须在定义行或在静态初始化程序块中。

这里有the Java tutorial关于静态初始化块的说法:

  

当初始化值可用且初始化可以放在一行时,这很有效。然而,这种形式的初始化由于其简单性而具有局限性。如果初始化需要一些逻辑(例如,错误处理或for循环来填充复杂的数组),则简单的赋值是不合适的。实例变量可以在构造函数中初始化,其中可以使用错误处理或其他逻辑。为了为类变量提供相同的功能,Java编程语言包括静态初始化块。

     

注意:没有必要在类定义的开头声明字段,尽管这是最常见的做法。只有在使用它们之前才需要声明和初始化它们。

实例字段

在我们处理此问题时,必须在实例初始化完成时为分配一个final 实例(非静态)字段一个值即可。这意味着有三个地方可以初始化一个(但你必须选择一个):

1。定义行:

// For when you know the answer
class Foo {
    final int theAnswer = 42;
}

2。构造

// For when you need to have the answer passed in
class Foo {
    final int theAnswer;

    Foo(int answer) {
        theAnswer = answer;
    }
}

// Or for when you need to do some computation
class Bar {
    static final int ANSWER_COUNT = 10;
    final int[] answers;

    Foo() {
        answers = new int[ANSWER_COUNT];
        for (int i = 0; i < ANSWER_COUNT; i++) {
            answers[i] = i;
        }
    }

3。初始化程序块:

// For when you need to do some computation and have many constructors
class Bar {
    static final int ANSWER_COUNT = 10;
    final int[] answers;

    {
        answers = new int[ANSWER_COUNT];
        for (int i = 0; i < ANSWER_COUNT; i++) {
            answers[i] = i;
        }
    }

    // I have many constructors and don't want to copy-paste 
    // the initialization logic above to all of them
    Bar() { ... }
    Bar(int i) { ... }
    Bar(String blah) { ... }
}

the same page in the tutorial开始,关于初始化程序块:

  

Java编译器将初始化程序块复制到每个构造函数中。因此,这种方法可用于在多个构造函数之间共享代码块。

答案 2 :(得分:1)

在您发布的代码中,字段为static,因此可以从静态初始化块中获取值:

static {
    str = "my string";
}

对于非static字段,它们可以在构造函数中初始化,也可以在实例初始化程序块中初始化:

class TestClass {
    private final String str;

    {
        str = "my string";
    }

    TestClass() {

    }
}