Javaでオブジェクトの配列を作成する


196

私はJavaを初めて使用し、しばらくの間、Javaでオブジェクトの配列を作成しました。

たとえばクラスAがあります-

A[] arr = new A[4];

しかし、これはA4つのオブジェクトではなく、4つのオブジェクトへのポインタ(参照)を作成するだけです。これは正しいです?作成されたオブジェクトの関数/変数にアクセスしようとすると、nullポインター例外が発生します。オブジェクトを操作/アクセスできるようにするには、これを行う必要がありました:

A[] arr = new A[4];
for (int i = 0; i < 4; i++) {
    arr[i] = new A();
}

これは正しいですか、それとも私は何か間違っていますか?これが正しければ、それは本当に奇妙です。

編集:私はこれが奇妙だと思います。C++では単にnew A[4]と言って4つのオブジェクトを作成するからです。


17
これは非常に役立つ質問だと言いたかっただけです。聞いてくれてありがとう
パンドリム

回答:


262

これは正しいです。

A[] a = new A[4];

... Aこれを行うのと同様に、4つの参照を作成します。

A a1;
A a2;
A a3;
A a4;

今、あなたはこのようにa1.someMethod()割り当てずに行うことができませんでしたa1

a1 = new A();

同様に、配列でこれを行う必要があります:

a[0] = new A();

...使用する前に。


10
この答えは私にたくさんの混乱を救いました、その存在をありがとう。
パンドリム

1
私もこの混乱を抱えていました。私はC ++の出身なので、C ++のように、Javaのnewキーワードもコンストラクターを呼び出してIメモリーを割り当てるといつも思っていました。Java newでは、C ++と比較して、実際のオブジェクトではなく参照のみを作成すると思います。ご回答ありがとうございます。
クリシュナオザ2015年

1
@ Krishna_Oza、C ++との違いはありません。最初newは配列オブジェクトを作成します。これらは動的に割り当てられたオブジェクト(「ヒープ」)です。したがって、類似のC ++コードは次のようになりますA **a = new A*[4]; for (int i = 0; i < 4; ++i) { a[i] = new A(); }
Vsevolod Golovanov 2016

1
私は新しい作成が参照を作成することを理解していますが、C ++のように配列の各要素のコンストラクタも初期化しないのはなぜですか。これはばかげているかもしれませんが、もしそうした場合、私たちが抱えるどんな問題でも尋ねたいと思いますか?@MeBigFatGuy
Jasser

2
@Jasser-要素のどのコンストラクタを呼び出しますか?唯一の要素コンストラクターが多数の引数を取る場合はどうなりますか?それらのオブジェクトをどのように作成しますか?
MeBigFatGuy

77

これは正しいです。あなたも行うことができます:

A[] a = new A[] { new A("args"), new A("other args"), .. };

この構文は、メソッド引数などの任意の場所で配列を作成および初期化するためにも使用できます。

someMethod( new A[] { new A("args"), new A("other args"), . . } )

34

はい、参照のみが作成され、デフォルト値nullに設定されます。そのため、NullPointerExceptionが発生します。オブジェクトを個別に作成し、参照を割り当てる必要があります。Javaで配列を作成するには3つのステップがあります-

宣言 –このステップでは、作成する配列のデータ型と次元を指定します。ただし、寸法のサイズについてはまだ触れていません。彼らは空のままです。

インスタンス化 –このステップでは、新しいキーワードを使用して、配列を作成するか、配列にメモリを割り当てます。このステップでは、配列の次元のサイズについて言及します。

初期化 –配列は常にデータ型のデフォルト値に初期化されます。ただし、独自の初期化を行うことができます。

Javaでの配列の宣言

これが、Javaで1次元配列を宣言する方法です。

int[] array;
int array[];

配列を宣言するには、前の構文を使用することをお勧めします。法的宣言の他の例をいくつか示します–

// One Dimensional Arrays
int[] intArray;             // Good
double[] doubleArray;

// One Dimensional Arrays
byte byteArray[];           // Ugly!
long longArray[];

// Two Dimensional Arrays
int[][] int2DArray;         // Good
double[][] double2DArray;

// Two Dimensional Arrays
byte[] byte2DArray[];       // Ugly
long[] long2DArray[];

そして、これらは違法な宣言のいくつかの例です–

int[5] intArray;       // Don't mention size!
double{} doubleArray;  // Square Brackets please!

インスタンス化

これが、「インスタンス化」、つまり配列にメモリを割り当てる方法です–

int[] array = new int[5];

JVMはnewキーワードを検出すると、何かにメモリを割り当てる必要があることを理解します。また、を指定することでint[5]intサイズ5のsの配列が必要であることを意味します。したがって、JVMはメモリを作成し、新しく割り当てられたメモリの参照を、タイプの「参照」である配列に割り当てますint[]

初期化

ループの使用– forループを使用して配列の要素を初期化することは、配列を実行する最も一般的な方法です。デフォルト値自体を割り当てる場合は、JVMが代わりにループを実行するため、forループを実行する必要はありません。

オールインワン..!–アレイの宣言、インスタンス化、初期化を一度に実行できます。構文は次のとおりです–

int[] arr = {1, 2, 3, 4, 5};

ここでは、JVMが5つの値を提供していることがわかるため、サイズについては触れません。

したがって、インスタンス化するまで、参照はnullのままです。私の答えがあなたの役に立ったといいのですが。:)

ソース-Javaの配列


5

以下は、パラメーターを取るコンストラクターを使用して、10個の従業員オブジェクトの配列を作成する明確な例です。

public class MainClass
{  
    public static void main(String args[])
    {
        System.out.println("Hello, World!");
        //step1 : first create array of 10 elements that holds object addresses.
        Emp[] employees = new Emp[10];
        //step2 : now create objects in a loop.
        for(int i=0; i<employees.length; i++){
            employees[i] = new Emp(i+1);//this will call constructor.
        }
    }
}

class Emp{
    int eno;
    public Emp(int no){
        eno = no;
        System.out.println("emp constructor called..eno is.."+eno);
    }
}

3

あなたは正しいです。それとは別に、Java 8(ストリームAPIを導入)以降、次のように、「ファクトリー」から提供された要素で満たされた特定のサイズの配列を作成する場合は、このワンライナーを使用できます。

A[] a = Stream.generate(() -> new A()).limit(4).toArray(A[]::new);
  • Stream.generate(() -> new A())ラムダによって記述された方法で作成された個別のA要素のファクトリのような() -> new A()ものです。これは、実装でありSupplier<A>、新しいAインスタンスをそれぞれ作成する方法を記述します。
  • limit(4)ストリームが生成する要素の量を設定します
  • toArray(A[]::new)(として書き換えることもtoArray(size -> new A[size])できます)-返される配列のタイプを決定/説明できます。

一部のプリミティブタイプでは、、を使用できます。これDoubleStreamによりIntStream、のLongStreamようなジェネレータが提供されますが、他のジェネレータはrange rangeClosedほとんどありません。


0

はい、Javaでは正しいです。オブジェクトの配列を作成するには、いくつかの手順があります。

  1. 宣言してからインスタンス化する( '4'オブジェクトを格納するメモリを作成する):

    A[ ] arr = new A[4];
  2. オブジェクトの初期化(この場合、クラスAの4つのオブジェクトを初期化できます)

    arr[0] = new A();
    arr[1] = new A();
    arr[2] = new A();
    arr[3] = new A();

    または

    for( int i=0; i<4; i++ )
      arr[i] = new A();

これで、作成したオブジェクトなどから既存のメソッドの呼び出しを開始できます。

例えば:

  int x = arr[1].getNumber();

または

  arr[1].setNumber(x);

0

ジェネリッククラスの場合、ラッパークラスを作成する必要があります。例えば:

Set<String>[] sets = new HashSet<>[10]

結果:「ジェネリック配列を作成できません」

代わりに使用:

        class SetOfS{public Set<String> set = new HashSet<>();}
        SetOfS[] sets = new SetOfS[10];  

この行は、セットのタイプが文字列であるセットの配列を作成しようとしていることを意味しますか?
sofs1 2018

0

Javaで新しい配列を宣言する一般的な形式は次のとおりです。

type arrayName[] = new type[numberOfElements];

typeはプリミティブ型またはオブジェクトです。numberOfElements配列に格納する要素の数であり、この値は変更できません。Javaは動的配列をサポートしていないため(オブジェクトを保持するために柔軟で動的な構造が必要な場合は、Javaコレクションの一部を使用することができます)。

5人の小さな会社の全従業員の給与を格納する配列を初期化します。

int salaries[] = new int[5];

配列のタイプ(この場合はint)は、配列内のすべての値に適用されます。1つの配列にタイプを混在させることはできません。

salaries配列が初期化されたので、値を入れたいと思います。これは、次のような初期化中に行うことができます。

int salaries[] = {50000, 75340, 110500, 98270, 39400};

または、後でこのようにそれを行うには:

salaries[0] = 50000;
salaries[1] = 75340;
salaries[2] = 110500;
salaries[3] = 98270;
salaries[4] = 39400;

配列作成のより視覚的な例: ここに画像の説明を入力してください

配列の詳細については、ガイドをご覧ください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.