2013-06-02 3 views
0

자바 클래스 파일 형식을 배우려고하고 ConstantValue 속성 아래에 상수 변수 값이 저장되어 있다는 것을 알고 있습니다. 상수 필드 값은 클래스 파일에 저장됩니다. 예 :여기서 클래스 파일에 저장된 변수의 초기 값은 무엇입니까?

public Robot robot = new Robot(); 

나는 oracles 클래스 파일 사양을 검토 한 결과 이와 같은 속성을 찾을 수 없습니다.

+0

값이 상수가 아니므로 클래스 파일에 저장할 수 없습니다. –

답변

2

초기 값을 저장하기위한 유일한 속성은 ConstantValue입니다. 그러나 이것은 정적 변수에만 사용됩니다. 자바 컴파일 코드에서는 정적 최종 변수에만 사용되지만 필기 바이트 코드의 정적 변수에는 사용할 수 있습니다. 물론이 값은 일정해야합니다.

게시 한 예제의 경우, 사용자는 이니셜 라이저으로 알려져 있습니다. 이것들은 클래스 파일에는 해당하지 않습니다.대신 모든 수퍼 클래스 생성자 호출이 반환 된 후에 Java 컴파일러에서이 코드를 붙여 넣습니다. 이것은 수퍼 클래스 생성자에서 가상 메소드를 호출하는 것과 같이이 시점 이전에 볼 수있는 경우 아직 초기화되지 않았 음을 의미합니다.

다음은 예입니다.

public class initializers { 

    static final float f = 4; 
    static final int i = int.class.hashCode(); 
    static int i2 = 4; 

    public final Object x = null; 
    public Object x2 = null; 


    public initializers() {} 
    public initializers(int x) {this();} 
    public initializers(float x) {} 
} 

컴파일하고 당신이 볼 수 있듯이

.version 49 0 
.class super public initializers 
.super java/lang/Object 

.field static final f F = 4.0F 
.field static final i I 
.field static i2 I 
.field public final x Ljava/lang/Object; 
.field public x2 Ljava/lang/Object; 

.method public <init> :()V 
    .limit stack 2 
    .limit locals 1 
    aload_0 
    invokespecial java/lang/Object <init>()V 
    aload_0 
    aconst_null 
    putfield initializers x Ljava/lang/Object; 
    aload_0 
    aconst_null 
    putfield initializers x2 Ljava/lang/Object; 
    return 
.end method 

.method public <init> : (I)V 
    .limit stack 1 
    .limit locals 2 
    aload_0 
    invokespecial initializers <init>()V 
    return 
.end method 

.method public <init> : (F)V 
    .limit stack 2 
    .limit locals 2 
    aload_0 
    invokespecial java/lang/Object <init>()V 
    aload_0 
    aconst_null 
    putfield initializers x Ljava/lang/Object; 
    aload_0 
    aconst_null 
    putfield initializers x2 Ljava/lang/Object; 
    return 
.end method 

.method static <clinit> :()V 
    .limit stack 1 
    .limit locals 0 
    getstatic java/lang/Integer TYPE Ljava/lang/Class; 
    invokevirtual java/lang/Object hashCode()I 
    putstatic initializers i I 
    iconst_4 
    putstatic initializers i2 I 
    return 
.end method 

에서 클래스 결과 분리력, fConstantValue 속성을 사용하는 유일한 하나입니다. i은 상수 표현이 아니기 때문에 진수가 아니기 때문에 i2은 최종이 아니기 때문에 진리가 아닙니다. ii2을 초기화하는 코드는 정적 초기화 프로그램 ('클래스 생성자')에 포함되었습니다. xx2을 초기화하는 코드는 두 개의 수퍼 클래스 생성자 호출 뒤에 붙여 넣었지만 두 번째 생성자에서는 동일한 클래스의 생성자를 호출하지 않았습니다.

+0

@JB 당신 말이 맞아요, 그들은 공개 일 필요는 없습니다. – Antimony

0

붙여 넣은 코드에 상수가 없습니다. 변수가 있습니다 (런타임시 스택에 할당 됨).

정수 필드가 아닌 클래스의 바이트 코드에 관심이 있으시면 을 사용해보십시오.


변수 robot은 런타임에 초기화됩니다. 말, robot 클래스 Foo에 있습니다

class Foo { 
    public Robot robot = new Robot(); 
    Foo() { 
    } 
} 

이제 자바 컴파일러는 다음 단계를 실행하는 일련의 명령에 new Foo() 변환합니다 :

  • 이 힙에 새 개체 Foo을위한 공간을 할당합니다. 여기에는 필드 공백이 포함됩니다.robot.
  • 점프는 푸 이니셜이 Robot
  • Foo
  • 전화 이니셜의 부모의 Robot
  • 전화 생성자의 새로운 인스턴스를위한 공간을 할당 Foo
    • 클래스의 지침을 초기화하는 ...

    그래서 바이트 코드에 무엇인가 결론은 바이트 코드에서 필드 로봇에 대한 공간이 없습니다 Robot

  • 의 할당 및 초기화 Foo

  • 지침의 할당 및 초기화

    • 지침입니다 클래스 파일 런타임에 실행되는 할당 명령어가 있으며 힙의 필드 공간을 만듭니다.


  • +0

    하지만 변수가 초기화되는 시점은 – Popgalop

    +0

    잘못된 변수는 선언 된 위치에 따라 스택 또는 힙에 저장됩니다. 메서드 로컬 변수 인 경우에만 스택으로 이동하고 그렇지 않으면 스택으로 이동합니다. –

    +0

    @JunedAhsan 질문은 필드에 대해 이야기 했으므로 필드가 아니라 로컬 변수라고 가정했습니다. 나는 또한 대답에 약간의 설명을 추가했다 – Mifeet