2

是否可以为程序中其他任何地方的最终变量赋值?还是必须在创建时为它们分配一个值?

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

3 回答 3

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; }
}
于 2012-04-25T01:45:49.383 回答
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 静态字段,除了假定它们将在某个时间点被访问,因此它们必须在定义行或静态初始化块中进行初始化。

以下是Java 教程中关于静态初始化块的内容:

当初始化值可用并且初始化可以放在一行时,这很有效。但是,这种形式的初始化由于其简单性而具有局限性。如果初始化需要一些逻辑(例如,错误处理或填充复杂数组的 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) { ... }
}

教程的同一页面中,关于初始化块:

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

于 2012-04-25T01:59:20.267 回答
1

在您发布的代码中,该字段static可以从静态初始化块中获得一个值:

static {
    str = "my string";
}

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

class TestClass {
    private final String str;

    {
        str = "my string";
    }

    TestClass() {

    }
}
于 2012-04-25T01:47:01.460 回答