2013-12-17 5 views
4

List, Vector 또는 다른 것과 같은 일반 클래스를 사용하면 size() 함수를 사용하여 클래스의 길이를 반환하지만, 클래스 또는 기본 데이터 형식 배열의 현재 길이를 반환하는 public 멤버 길이를 가져옵니다.배열은 Java의 ByteCode에서 어떻게 작동합니까?

int a[] = new int[3]; 
a.length; // used without() 

Vector<Integer> v = new Vector<Integer>(); 
v.length(); // used with() 

왜 그렇습니까? 나는 배열 자체 클래스가 아니라는 뜻인가요? 따라서 클래스가 없으면 멤버를 식별 할 수 없습니다. 내가 백그라운드 (ByteCode)에서 어떻게 처리되는지 알 수 없다. 메모리의 배열은 배열의 첫 번째 요소에 대한 포인터와 함께 저장되며 인덱스 (i)는 메모리 포인터가 ArrayPointer + i*(size of DataType)으로 이동한다는 것을 알고 있습니다.

이제 컴퓨터가 배열의 모든 요소를 ​​통과하고 모든 요소를 ​​계산한다고 말할 수 있지만 배열이 끝나는 위치와 다음 시작 위치를 컴퓨터가 어떻게 알 수 있습니까? 그리고 크기가 저장되는 배열의 '멤버 varaible'은 어디에서 오는가?

우리는 배열을 너무 자주 사용하지만 ByteCode의 Java 코드 뒤에 어떤 일이 일어나는지 거의 알지 못합니다. 어떻게 가능한지 설명해 주시겠습니까?

+1

.method static public main : ([Ljava/lang/String;)V .limit stack 1 .limit locals 1 aload_0 getfield [Ljava/lang/String; length I return .end method 

결과 배열은 다른 같은 목적으로한다. '길이'는 공개 필드입니다. –

+0

이것은 좋은 설명이다. (https://www.artima.com/underthehood/objectsP.html). – Brian

+1

http://stackoverflow.com/questions/5950155/how-is-length-implemented-in-java-arrays – assylias

답변

12

배열은 Java의 객체이지만 실제 클래스에는 해당하지 않습니다. 사실 JVM은 암시 적으로 배열 클래스를 즉시 생성하지만 성능상의 이유로 실제 클래스는 아닙니다.

개체이므로 개체 필드에 저장하고 일반처럼 전달할 수 있습니다.그러나 바이트 코드 수준에서는 조금 다르게 처리됩니다.

먼저 배열은 단일 차원 프리미티브, 단일 차원 개체 및 다차원 배열에 대해 newarray, anewarray 또는 multinewarray 지침으로 각각 만들어집니다. 반대로 일반 오브젝트는 new 명령어로 생성됩니다.

요소 가져 오기 및 설정은 *aload*astore 명령으로 수행됩니다.

또한 x.length는 실제 필드가이 아닙니다. 대신 arraylength 명령어로 컴파일됩니다. 이것은 다음 코드를 컴파일하여 볼 수 있습니다. 다음의 바이트 코드를 수동 예외 야기 할 바이트 코드를 생성하여 length 필드를 액세스하려고

.method public test : (I)V 
    .limit stack 2 
    .limit locals 4 
    iload_1 
    newarray int 
    astore_2 
    iload_1 
    anewarray java/lang/String 
    astore_3 
    getstatic java/lang/System out Ljava/io/PrintStream; 
    aload_2 
    arraylength 
    invokevirtual java/io/PrintStream println (I)V 
    getstatic java/lang/System out Ljava/io/PrintStream; 
    aload_3 
    arraylength 
    invokevirtual java/io/PrintStream println (I)V 
    return 
.end method 

public void test(int size){ 
    int[] x = new int[size]; 
    String[] y = new String[size]; 
    System.out.println(x.length); 
    System.out.println(y.length); 
} 

결과 필드 않기 때문에 실제로 존재하지.

Exception in thread "main" java.lang.VerifyError: Expecting reference to class i 
n class ArrayTest at constant pool index 30 in method ArrayTest.main([Ljava/lang 
/String;)V 
     at java.lang.Class.getDeclaredMethods0(Native Method) 
     at java.lang.Class.privateGetDeclaredMethods(Unknown Source) 
     at java.lang.Class.getMethod0(Unknown Source) 
     at java.lang.Class.getMethod(Unknown Source) 
     at sun.launcher.LauncherHelper.getMainMethod(Unknown Source) 
     at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source) 
+0

와우 감사합니다. 이것이 Java 코드의 논리를 이해하기 위해 내가 원했던 대답이었습니다. 고맙습니다. :) – Cilenco

+0

@Cilenco 그렇다면 대답을 수락해야합니다. – Antimony

+0

그래서 명확하게하기 위해,'.length'를 사용하는 것 이외에 자바에서 배열의 길이에 접근 할 수있는 방법이 없습니까? –

0

배열은 실제로 클래스이며, 다른 클래스와 마찬가지로 Object를 확장하지만 더 나은 성능과 편리 성을 위해 언어로 내부적으로 처리됩니다. 클래스는 필드와 메서드를 가질 수 있습니다.

0

의 배열은 단순히 객체 값으로 배열을 할당하여이 직접 시도 할 수있는 개체입니다. 당신이 배열 바이트 수준이 무엇인지 알고 싶다면

public Object test(){ 
    int[] test = new int[5]; 
    Object obj = test; 
    return obj; 
} 

가 : 배열 자체가 바로 배열, 다른 정보의 길이에 대한 정보의 비트와 포인터에 대한 포인터 예를 들어 데이터를 저장할 수있는 예약 된 메모리 조각 (배열의 크기와 동일한 순차 메모리). 데이터에 접근하는 것은 [pointer] + [indexnumber] * [sizeofeachitem]을 찾는 간단한 문제이며, 그러면 어떤 메모리 조각을 볼 것인지를 알 수 있습니다.

-1

실제로 배열 유형은 클래스입니다! 메모리에 저장된대로 기본 클래스 정보 (포함 된 요소의 클래스 정보가 포함되지 않은 경우 해당 클래스의 정보 포함), 보유한 요소의 수 및 실제 배열 데이터를 따릅니다. length은 배열이 다른 수의 요소를 보유하지 않기 때문에 메서드가 아닌 final 필드입니다.

Vector과 같은 다른 종류의 구조체의 경우 개체의 요소 수가 순간적으로 바뀔 수 있으므로 length()이 메서드 여야합니다. 마찬가지로 String : String 클래스가 불변 인 경우에도 length() 메서드는 CharSequence에서 상속됩니다. 어떤 종류의 CharSequence은 길이가 가변적 일 수 있으므로 다시 메소드로 구현됩니다.

+0

x.length는 arraylength 명령으로 컴파일됩니다. 그것은 실제 분야가 아닙니다. – Antimony

+0

@Antimony 배열의 길이는 실제로 데이터의 헤더에 저장되므로 다른 클래스와 동일하게 처리되지 않을 수도 있습니다. 배열 클래스의 효과적인 구현을위한 문서조차도 JVM에서 저수준 데이터로 취급 되더라도 'public final'필드로 'length'를 참조합니다. – Mumbleskates

+0

바이트 코드 수준과 바이트 코드 수준에 대해 질문하는 경우를 제외하고는 해당 필드가 없습니다. 특수 교육으로 구현됩니다. – Antimony

관련 문제