質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.23%

インスタンスの生成を配列で行うときの初期化子について

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 3,551

ramune3

score 9

質問内容

Javaを学んで約2か月です。
Mainメソッドから呼んだ、処理を行うクラスのフィールドで、配列を用いて別のクラスのインスタンスを生成したいです。
以下のソースコードで生成したところ、「メソッド名が無いのにどのように呼び出すのか」という指摘を受けました。
コンパイル、実行共にできています。

・初期化子にはその配列に格納したいデータを入れる
・int[] hoge = new int[]{10,20,30};もしくは、int[] hoge = {10,20,30}のような使い方が正しい使い方である

以上のように配列の記述方法を認識しています。
指摘を受けるまでは、”初期化子としてFor文を記述しているので、メソッド内で記述していなくても動作するのではないか”、と考えていました。
その後、検索をしたり、テキストを読み直してもこの書き方をしている物が見当たらないので、書き方が誤っているのだろう、というのは見当が付きました。

・なぜメソッドが無いのにこの書き方でエラーが起きないのか
・フィールドで配列を用いてインスタンス生成したいときの正しい記述方法
以上の2点について教えていただきたいです。
よろしくお願いします。

該当のソースコード

public class Hoge{
//その他に変数を3つ定義中
    HogeHoge[] hoge = new HogeHoge[10];{
        for(int i = 0; i <= 9; i++){
            hoge[i] = new HogeHoge();
        }
    } //以下にメソッドが2つ
}

試したこと

HogeHoge[] hoge = new HogeHoge[10]{
    for(int i = 0; i <= 9; i++){
       hoge[i] = new HogeHoge();
    }
 }


→エラー:';'がありません
その他、該当部分のどこかをいじるとFor文以降がコンパイルエラーになります。
この書き方以外ではエラーが起こるのになぜこれだけ問題なく動く…?と疑問が深まるばかりでした。

//インスタンス生成を行うためのメソッドを作成
public static void main(String[] args){
    HogeHoge[] hoge = new HogeHoge[10];{
         for(int i = 0; i <= 9; i++){
             hoge[i] = new HogeHoge();
        }
    }
}


→同一クラス内のメソッドにhogeが存在しない旨のエラーが表示される(ほかのメソッドからスコープ範囲外になるのでエラーになると認識しています。)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+3

・なぜメソッドが無いのにこの書き方でエラーが起きないのか 

Javaには初期化ブロックという仕様があります。偶然、初期化ブロックの記述方法になっているのでエラーにはなりません。

・フィールドで配列を用いてインスタンス生成したいときの正しい記述方法 

インスタンス作成時に一度だけ初期化するならコンストラクタや初期化ブロックに書くといいですが、何度も初期化をするなら初期化処理をそのままメソッド化しておくべきですね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/29 16:24

    初期化ブロックの仕様は理解すべきです。
    問題なのはあなた以外の開発者です。
    あなたは今回のことで初期化ブロックを理解すると思いますが、他の方ももしかしたらあなたと同じつまずきをする可能性があります。

    キャンセル

  • 2017/05/29 16:29

    他の方のことも考えて理解するべきなんですね。
    わかりました。調べてみます。
    ありがとうございます。

    キャンセル

  • 2017/05/29 17:23

    質問内容のプログラムに関して、
    >コンストラクタでメソッドを呼び出す
    こちらのやり方で、初期化ブロックを使用せずに動作することができました!
    初期化ブロック、インスタンスイニシャライザに関しては、引き続き正しく理解し、他の方が同じ躓きをしているときに対処できるよう勉強していきます。
    丁寧な回答ありがとうございました。

    キャンセル

+3

最初のコードは、以下のように解釈されます。

public class Hoge{
    // ここで配列を宣言(nullで埋められる)
    HogeHoge[] hoge = new HogeHoge[10];

    // 以下のブロックは「インスタンスイニシャライザ」として、
    // インスタンス生成のたびに実行される
    {
        for(int i = 0; i <= 9; i++){
            hoge[i] = new HogeHoge();
        }
    } //以下にメソッドが2つ
}

ただ、一般に「インスタンスイニシャライザ」は積極的に活用するものではなく、コンストラクタ内に同等のコードを書くのが一般的です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/29 15:59

    ```Java
    public class Hoge{
    HogeHoge[] hoge = new HogeHoge[10];
    }
    ```
    ```Java
    public class HogeHoge{
    HogeHoge(){ for(int i = 0; i <= 9; i++){
    new HogeHoge();
    }
    }
    ```
    ということでしょうか。

    new HogeHoge[10];
    のnewの後って、配列の形をしてますが、HogeHoge()と同じでコンストラクタを呼び出す役割ということですか?
    次々質問して申し訳ありません。

    キャンセル

  • 2017/05/29 16:07

    すみません、上の書き込みだとHogeの時点でnewをしているので、コンストラクタは不要ということですね。
    もういちどじっくり考えてから再度質問します。

    キャンセル

  • 2017/05/29 17:17 編集

    public class Hoge{
    HogeHoge[] hoge =new HogeHoge[10];
    Hoge(){
    for(int i = 0; i <= 9; i++){
    hoge[i] = new HogeHoge();
    }
    }
    上記のように作成いたしました。
    HogeのフィールドでHogeHoge配列を宣言し、Hogeが呼び出されたときに、Hogeのコンストラクタ内で配列の初期化を行う、ということですね!
    丁寧な回答ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる