web-dev-qa-db-ja.com

配列のlengthプロパティはどこで定義されていますか?

パブリックメソッドsize()を使ってArrayList<E>の長さを決めることができます。

ArrayList<Integer> arr = new ArrayList(10);
int size = arr.size();

同様に、Arrayプロパティを使ってlengthオブジェクトの長さを決定することができます。

String[] str = new String[10];
int size =  str.length;

ArrayListsize()メソッドはArrayListクラス内で定義されていますが、lengthのこのArrayプロパティはどこで定義されていますか?

258
NINCOMPOOP

配列はJavaの特別なオブジェクトです。それらはlengthという単純な属性を持ちます。これはfinalです。

配列の "クラス定義"はありません(あなたはそれをどの.classファイルにも見つけることができません)、それらは言語自体の一部です。

10.7。配列メンバー

配列型のメンバーは以下のすべてです。

  • publicfinalフィールドlengthは、配列の構成要素の数を含みます。 lengthは正数またはゼロです。
  • publicメソッドcloneは、クラスObject内の同じ名前のメソッドをオーバーライドし、チェック済みの例外をスローしません。配列型T[]cloneメソッドの戻り型はT[]です。

    多次元配列のクローンは浅い、つまり新しい配列を1つだけ作成するということです。サブアレイは共有されています。

  • すべてのメンバはクラスObjectから継承しました。継承されていないObjectの唯一のメソッドは、そのcloneメソッドです。

リソース:

247
Colin Hebert

それは基本的に "特別"で、それ自身のバイトコード命令arraylengthを持っています。だからこの方法:

public static void main(String[] args) {
    int x = args.length;
}

このようにバイトコードにコンパイルされます。

public static void main(Java.lang.String[]);
  Code:
   0:   aload_0
   1:   arraylength
   2:   istore_1
   3:   return

そのため、通常のフィールドのようにはアクセスされません。確かに、このように通常のフィールドであるかのように取得しようとすると失敗します。

// Fails...
Field field = args.getClass().getField("length");
System.out.println(field.get(args));

そのため、残念ながら、public finalフィールドlengthを持つ各配列型のJLS記述はやや紛らわしい:(

114
Jon Skeet

Java言語仕様で定義されています

配列型のメンバーは以下のすべてです。

  • 配列の要素数を含むpublic finalフィールドlengthlengthは正またはゼロです。

無制限の数の配列型があるので(すべてのクラスに対して対応する配列型があり、 次に 多次元配列があります)、それらをクラスファイルに実装することはできません。 JVMはその場でそれをしなければなりません。

18

これは質問に対する直接的な答えではありませんが、.length vs .size()引数への追加です。私はこの質問に関連した何かを研究していたので、それに出会ったとき私はここに提供された定義があることに気づいた

配列の要素数 を含むpublic finalフィールドの長さ。

「正確に」正しくありません。

フィールド長には、配列内に存在するコンポーネントの数ではなく、コンポーネントを配置するために使用可能な の場所の数 が含まれます。つまり、その配列に割り当てられている使用可能なメモリの合計を表します。そのメモリのうちどれだけが使用されているかではありません。

Array Memory Allocation

例:

static class StuffClass {
    int stuff;
    StuffClass(int stuff) {
        this.stuff = stuff;
    }
}

public static void main(String[] args) {

    int[] test = new int[5];
    test[0] = 2;
    test[1] = 33;
    System.out.println("Length of int[]:\t" + test.length);

    String[] test2 = new String[5];
    test2[0] = "2";
    test2[1] = "33";    
    System.out.println("Length of String[]:\t" + test2.length);

    StuffClass[] test3 = new StuffClass[5];
    test3[0] = new StuffClass(2);
    test3[1] = new StuffClass(33);
    System.out.println("Length of StuffClass[]:\t" + test3.length);         
}

出力:

Length of int[]:        5
Length of String[]:     5
Length of StuffClass[]: 5

ただし、ArrayList.size()プロパティは、リスト内の要素数を示します。

ArrayList<Integer> intsList = new ArrayList<Integer>();
System.out.println("List size:\t" + intsList.size());
intsList.add(2);
System.out.println("List size:\t" + intsList.size());
intsList.add(33);
System.out.println("List size:\t" + intsList.size());

出力:

List size:  0
List size:  1
List size:  2
15
nem035

これは公開された最終フィールドで、配列の要素数が含まれています(長さは正またはゼロになります)。

したがって、配列は次のクラスと同じパブリックフィールドおよびメソッドを持ちます。

class A implements Cloneable, Java.io.Serializable {
    public final int length = X;
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e.getMessage());
        }
    }
}

詳細情報

10.7配列メンバ

http://Java.Sun.com/docs/books/jls/second_edition/html/arrays.doc.html

5

キーワードの長さは、定義されたデータフィールドのように機能します。配列内で使用するときは、配列内の要素数にアクセスするためにそれを使用できます。 String []に関しては、Stringクラスで定義されたlength()メソッドを呼び出すことができます。 ArrayListに関しては、ArrayListで定義されているsize()メソッドを使うことができます。 ArrayList <>(capacity)を使用して配列リストを作成する場合、要素がないため、この配列リストの初期サイズ()は0になります。

0
Xiaogang

そのまま答えると、 配列のこのlengthプロパティはどこで定義されているのでしょうか ?特別なObject headerで。

_ jol _ で見やすい

 int [] ints = new int[23];
 System.out.println(ClassLayout.parseInstance(ints).toPrintable());

この出力からの行の1つは次のようになります。

OFFSET  SIZE      TYPE DESCRIPTION
16       4        (object header)   17 00 00 00 (00010111 00000000 00000000 00000000) (23)

通常、オブジェクトは2つのヘッダ(markとklass)を持ち、sizeintなので、配列はもう1つの長さで4 bytesを占有します。

0
Eugene