Programing

Java Final 변수에 기본값이 있습니까?

lottogame 2020. 10. 15. 07:22
반응형

Java Final 변수에 기본값이 있습니까?


다음과 같은 프로그램이 있습니다.

class Test {

    final int x;

    {
        printX();
    }

    Test() {
        System.out.println("const called");
    }

    void printX() {
        System.out.println("Here x is " + x);
    }

    public static void main(String[] args) {
        Test t = new Test();
    }

}

실행하려고하면 다음과 같이 컴파일러 오류가 발생합니다. variable x might not have been initializedJava 기본값에 따라 아래 출력을 올바르게 받아야합니까 ??

"Here x is 0".

최종 변수에 dafault 값이 있습니까?

이렇게 내 코드를 변경하면

class Test {

    final int x;

    {
        printX();
        x = 7;
        printX();
    }

    Test() {
        System.out.println("const called");
    }

    void printX() {
        System.out.println("Here x is " + x);
    }

    public static void main(String[] args) {
        Test t = new Test();
    }

}

다음과 같이 출력됩니다.

Here x is 0                                                                                      
Here x is 7                                                                                     
const called

누구든지이 행동을 설명해 주시겠습니까 ..


http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html , "인스턴스 멤버 초기화"장 :

Java 컴파일러는 이니셜 라이저 블록을 모든 생성자에 복사합니다.

즉 말하자면:

{
    printX();
}

Test() {
    System.out.println("const called");
}

정확히 다음과 같이 작동합니다.

Test() {
    printX();
    System.out.println("const called");
}

보시다시피 인스턴스가 생성되면 최종 필드는 확실히 할당 되지 않은 반면 ( http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html에서) # jls-8.3.1.2 ) :

빈 최종 인스턴스 변수는 선언 된 클래스의 모든 생성자 끝에 확실히 할당되어야합니다. 그렇지 않으면 컴파일 타임 오류가 발생합니다.

이있다 그래서, (적어도 내가 그것을 찾을 수 없어) 워드 프로세서에서 explitely 생성자가 끝나기 전에 최종 필드해야 일시적 걸릴 기본값을 언급하지 않는 것 동안 예측 값을 사용하면 경우 할당하기 전에 읽어보십시오.

기본값 : http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.5

두 번째 스 니펫에서 x는 인스턴스 생성시 초기화되므로 컴파일러가 불평하지 않습니다.

Test() {
    printX();
    x = 7;
    printX();
    System.out.println("const called");
}

또한 다음 접근 방식은 작동하지 않습니다. 최종 변수의 기본값 사용은 메소드를 통해서만 허용됩니다.

Test() {
    System.out.println("Here x is " + x); // Compile time error : variable 'x' might not be initialized
    x = 7;
    System.out.println("Here x is " + x);
    System.out.println("const called");
}

JLS생성자 (또는 거의 동일한 초기화 블록)의 빈 최종 인스턴스 변수에 기본값을 할당 해야 한다고 말합니다 . 이것이 첫 번째 경우에 오류가 발생하는 이유입니다. 그러나 이전에는 생성자에서 액세스 할 수 없다고 말하지 않습니다. 약간 이상해 보이지만 할당 전에 액세스 할 수 있으며 int-0의 기본값을 볼 수 있습니다.

UPD. @ I4mpi에서 언급했듯이 JLS 액세스 전에 각 값을 확실히 할당 해야한다는 규칙을 정의 합니다 .

Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.

그러나 생성자 및 필드와 관련 하여 흥미로운 규칙 이 있습니다.

If C has at least one instance initializer or instance variable initializer then V is [un]assigned after an explicit or implicit superclass constructor invocation if V is [un]assigned after the rightmost instance initializer or instance variable initializer of C.

따라서 두 번째 경우 값 x생성자의 끝에 할당이 포함되어 있기 때문에 생성자의 시작 부분에 확실히 할당 됩니다.


초기화하지 않으면 초기화되지 않았으므로 x컴파일 타임 오류가 발생 x합니다.

x최종적으로 선언 한다는 것은 생성자 또는 이니셜 라이저 블록 에서만 초기화 될 수 있음을 의미합니다 (이 블록은 컴파일러에 의해 모든 생성자로 복사되기 때문입니다).

0변수가 초기화되기 전에 인쇄 되는 이유 매뉴얼에 정의 된 동작 때문입니다 ( "기본값"섹션 참조).

기본값

It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style.

The following chart summarizes the default values for the above data types.

Data Type   Default Value (for fields)
--------------------------------------
byte        0
short       0
int         0
long        0L
float       0.0f
double      0.0d
char        '\u0000'
String (or any object)      null
boolean     false

The first error is the compiler complaining that you have a final field, but no code to initialize it - simple enough.

In the second example, you have code to assign it a value, but the sequence of execution means you reference the field both before and after assigning it.

The pre-assigned value of any field is the default value.


All non-final fields of a class initialize to a default value (0 for nummeric data types, false for boolean and null for reference types, sometimes called complex objects). These fields initialize before a constructor (or instance initialization block) executes independent of whether or not the fields was declared before or after the constructor.

Final fields of a class has no default value and must be explicitly initialized just once before a class constructor has finished his job.

Local variables on the inside of an execution block (for example, a method) has no default value. These fields must be explicitly initialized before their first use and it doesn't matter whether or not the local variable is marked as final.


Let me put it in the simplest words I can.

final variables need to be initialized, this is mandated by the Language Specification. Having said that, please note that it is not necessary to initialize it at the time of declaration.

It is required to initialize that before the object is initialized.

We can use initializer blocks to initialize the final variables. Now, initializer blocks are of two types static and non-static

The block you used is a non-static initializer block. So, when you create an object, Runtime will invoke constructor and which in turn will invoke the constructor of the parent class.

After that, it will invoke all the initializers (in your case the non-static initializer).

In your question, case 1: Even after the completion of initializer block the final variable remains un-initialized, which is an error compiler will detect.

In case 2: The initializer will initialize the final variable, hence the compiler knows that before the object is initialized, the final is already initialized. Hence, it will not complain.

Now the question is, why does x takes a zero. The reason here is that compiler already knows that there is no error and so upon invocation of init method all the finals will be initialized to defaults, and a flag set that they can change upon actual assignment statement similar to x=7. See the init invocation below:

enter image description here


As far as I'm aware, the compiler will always initialize class variables to default values (even final variables). For example, if you were to initialize an int to itself, the int would be set to its default of 0. See below:

class Test {
    final int x;

    {
        printX();
        x = this.x;
        printX();
    }

    Test() {
        System.out.println("const called");
    }

    void printX() {
        System.out.println("Here x is " + x);
    }

    public static void main(String[] args) {
        Test t = new Test();
    }
}

The above would print the following:

Here x is 0
Here x is 0
const called

If I try to execute it, i am getting compiler error as : variable x might not have been initialized based on java default values i should get the below output right??

"Here x is 0".

No. You are not seeing that output because you are getting a compile-time error in the first place. Final variables do get a default value, but the Java Language Specification (JLS) requires you to initialize them by the end of the constructor (LE: I'm including initialization blocks here), otherwise you'll get a compile-time error which will prevent your code to be compiled and executed.

Your second example respects the requirement, that's why (1) your code compiles and (2) you get the expected behaviour.

In the future try to familiarize yourself with the JLS. There's no better source of information about the Java language.

참고URL : https://stackoverflow.com/questions/24990691/will-java-final-variables-have-default-values

반응형