ジェネリクスクラス、汎用配列、コンパイルエラーについての質問

このQ&Aのポイント
  • 質問者は、ジェネリクスクラスについて調べていて、エラーに遭遇しました。
  • エラーの内容は「汎用配列を作成します」というもので、コンパイルができない状態です。
  • 質問者はこのエラーの意味についてググりましたが、理解できなかったため質問しました。
回答を見る
  • ベストアンサー

ジェネリクスクラス,汎用配列について質問です

以下のジェネリクスクラス"ESTack<E>"を作成し、 コンパイルをしようとしたところ、 エラー:汎用配列を作成します this.stk = new E[capacity]; ㅤㅤㅤㅤㅤ^ というエラーが表示されてしまい、コンパイルすることが出来ませんでした。 ----------------- class EStack<E>{ ㅤㅤㅤㅤprivate int max; ㅤㅤㅤㅤprivate int ptr; ㅤㅤㅤㅤprivate E[] stk; ㅤㅤㅤㅤpublic EStack(int capacity){ ㅤㅤㅤㅤㅤㅤㅤㅤthis.max = capacity; ㅤㅤㅤㅤㅤㅤㅤㅤthis.ptr = 0; ㅤㅤㅤㅤㅤㅤㅤㅤtry{ ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ this.stk = new E[capacity]; ㅤㅤㅤㅤㅤㅤㅤㅤ}catch(OutOfMemoryError e){ ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤthis.max = 0; ㅤㅤㅤㅤㅤㅤㅤㅤ} ㅤㅤㅤㅤ} (この後にはEStack<E>のインスタンスメソッド等が続きます) ------------------ そこで質問なのですが、"汎用配列を作成します"というエラーは 一体どういう意味なのでしょうか? 一応ググって調べてみましたが、良く分かりませんでした。

  • Java
  • 回答数3
  • ありがとう数6

質問者が選んだベストアンサー

  • ベストアンサー
  • root139
  • ベストアンサー率60% (488/809)
回答No.3

Javaではパラメータ化された型のコンストラクタを呼ぶ事や配列を作る事は出来ません。 Erasure (型消去)という仕組みにより、ジェネリック型自身のコンパイル時に実際の型が分からないもの(質問文の「E」など)については具象化不可能型となるからです。 (リフレクションなどを使えば話は別ですが) 下記のページに詳しい説明が有ります。 http://www.ibm.com/developerworks/jp/java/library/j-jtp01255/ この質問の件は、このページの「配列をコンストラクトする」の節に解説されています。 なお、Erasure は、ジェネリクスが導入される以前のコードとの相互運用に必要である為、将来的にも変わる可能性は低いでしょう。 また、『Effective Java』という本にジェネリックを使ったスタック実装の例が載っています。 http://www.amazon.co.jp/dp/4621066056 (「項目26 ジェネリック型を使用する」) この例に「汎用配列を作成します。」のエラーの解説も有りました。

akaragaostream
質問者

お礼

ありがとうございました

その他の回答 (2)

noname#207526
noname#207526
回答No.2

リフレクションなどを使うと出来ますよ。 http://d.hatena.ne.jp/Nagise/touch/20131121/1385046248

akaragaostream
質問者

お礼

ありがとうございました

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.1

こんにちは。 私も少々気になったのでググってみたところ、以下のページを見つけました。 http://www.geocities.jp/is3000nx/reading/tip/java.html#4 要するに、JavaのジェネリクスはC++のtemplateとは違うので、 this.stk = new E[capacity]; といった書き方はできないということですね。 記事では結局リフレクションを使って実現していますね。 ただ、この記事は10年ほど前の記事なので、Javaの最新バージョンでは事情が違っている可能性もありますが、そこまでは見つけることができませんでした。

akaragaostream
質問者

お礼

ありがとうございました

関連するQ&A

  • 多次元配列について

    int[]a = {1,2,3} int[]a = new int[3];//は普通の配列 int[]a = {{1,2,3},{4,5,6}}; int[][]a = new int[3][3]は //2次元配列 int[]a = {{1,2,3}{4,5,6}{7,8,9}};int[][][] = new int[3][3][3]; //は3次元配列 int[][][][]a = new int[3][3][3][3]; //は4次元配列になると思いますがこっちの方はコンパイルエラーが出ないのに int[][][][]a = {{1,2,3},{4,5,6},{7,8,9},{10,11,12}}; //はコンパイルエラーが出ます どうしてですか?

  • STLを使わずに可変長配列を再現する方法

    STLのlistが(配列に比べると)想像以上に遅かったので C++で可変長配列を再現したいのですけども 配列の拡張が思った以上に遅く困っています。 毎回newではオーバーヘッドが発生しますので、 現在は配列を一定数確保しておき 足りなくなったら配列を拡張(再確保)しています。 現在の配列のアドレスを一旦退避させてdeleteし、 新たにnewで生成して復帰させるといった感じです。 ただしこれでは、配列の要素数が増えるほど遅くなり、 オブジェクトの参照ならまだしも実体の場合は 全てコピーしなければならないので、 場合によってはSTLのlistよりも遅くなってしまいます。 newで生成してるのでできればreallocは使わずに 再現したいのですが、どうにか方法は無いでしょうか? よろしくおねがいします。 //----------------------------------------------- struct Test {   int val;   Test( int _val ){ val=_val; } }; Test obj1( 1 ); Test obj2( 2 ); Test obj3( 3 ); // 元のデータに代入 Test **ptr = new Test*[2]; ptr[0] = &obj1; ptr[1] = &obj2; // 退避させる Test **tmp = new Test*[2]; for( int i=0; i<2; i++ ) tmp[i] = ptr[i]; // 拡張する delete [] ptr; ptr = new Test*[4]; // 復帰させる for( int i=0; i<2; i++ ) ptr[i] = tmp[i]; delete [] tmp; ptr[2] = &obj3; //----------------------------------------------- ※NULLチェックなどはここでは省いています。

  • 配列

    public void test(int[] x){ ... } というメソッドに配列を渡したいとき、 test(new int[5]); は可能ですが、 int[] a = {0,1,2,1,0} という書式が可能なことから、 test( {0,1,2,1,0} ); としてみたのですが、コンパイルでひっかかります。 {}による配列生成は初期化のみに限定されているのでしょうか。 値の入った配列をこのtestに入れてやりたい場合は、 int[] a = {0,1,2,1,0}; test(a); としていかないといけないのでしょうか。

    • ベストアンサー
    • Java
  • C# 配列の変数宣言について。

    C#についての質問です。 新たなint型の配列dataを作るため変数宣言文を、以下のように書きました。 int[] data; すると、以下のような警告文が出ました。 『フィールド'IntArray.data'は割り当てられません。常に既定値nullを使用します。』 そこで調べてみたところ、「newしていないからこのような警告文が出る」ということがわかったので、以下のように書き換えました。 private int[] data = new int[]; すると今度は 『配列を作成するには、配列のサイズまたは配列の初期化子を指定する必要があります。』 というエラー文が出てしまいました。 このとき、配列のサイズも初期化子も指定したくない場合には、どのようにプログラムを書けば良いのでしょうか? お分かりになる方がいらっしゃいましたら、ご助言をお願いします。

  • C言語・スタックを使用した逆ポーランド記法について

    C言語でスタック(リスト構造)を使用した逆ポーランド記法のプログラムを作りたいのですが 計算式(例:1234+*+)が入力された場合、どのようにして数字と演算子を区別すればいいのでしょうか? 一応スタック構造の部分は、 #include <stdio.h> #include <stdlib.h> /*スタック構造*/ typedef struct stack { int max; int ptr; int *stk; } Stack; /*スタックの確保・初期化*/ int StackAlloc(Stack *s, int max) { s->ptr = 0; if ((s->stk = calloc(max, sizeof(int))) == NULL) { s->max = 0; return (-1); } s->max = max; return (0); } /*スタック解放*/ void StackFree(Stack *s) { if (s->stk != NULL) { free(s->stk); s->max = s->ptr = 0; } } /*プッシュ*/ int StackPush(Stack *s, int x) { if (s->ptr >= s->max) return (-1); s->stk[s->ptr++] = x; return (0); } /*ポップ*/ int StackPop(Stack *s, int *x) { if (s->ptr <= 0) return (-1); *x = s->stk[--s->ptr]; return (0); } /*データのピーク*/ int StackPeek(const Stack *s, int *x) { if (s->ptr <= 0) return (-1); *x = s->stk[s->ptr - 1]; return (0); } /*スタックの大きさを返却*/ int StackSize(const Stack *s) { return (s->max); } /*データを返却*/ int StackNo(const Stack *s) { return (s->ptr); } /*スタックは空か*/ int StackEmpty(const Stack *s) { return (s->ptr <= 0); } /*スタックは満杯か*/ int StackFull(const Stack *s) { return (s->ptr >= s->max); } /*スタックを空にする*/ void StackClear(Stack *s) { s->ptr = 0; } といった感じで仕上げています。

  • 2つの配列を1つの配列にする。

    JAVA初心者です。1日に何度も質問してしまってすいません。 問題 private static int[] concat(int[] ia1, int[] ia2) のメソードを使いarray1とarray2[の2つの配列が両方intのとき、array1 array2と続く配列を表示する。 private static int[] concat(int[] ia1, int[] ia2) { int e; for (e=0; e < ia1.length; e++) { } for (e=0; e < ia2.length; e++) { }     return new int[0]; } public static void main(String[]args){ int[] testIntArray1 = {1, 2, 8, 4}; int[] testIntArray2 = {99, 88, 77, 66}; // You should also test the case where the first // array is empty, the second array is empty, and // both arrays are empty. System.out.println("First test array for concat is: "); int e; for (e=0; e < testIntArray1.length; e++) { System.out.print(testIntArray1[e] + " "); } System.out.println(); System.out.println("Second test array for concat is: "); for (e=0; e < testIntArray2.length; e++) { System.out.print(testIntArray2[e] + " "); } System.out.println(); int[] result = concat(testIntArray1, testIntArray2); System.out.println("Result of concat is: "); for (e=0; e < result.length; e++) { System.out.print(result[e] + " "); } System.out.println(); //*********************************************************** 結果 First test array for concat is: 1 2 8 4 Second test array for concat is: 99 88 77 66 Result of concat is: 1 2 8 4 99 88 77 66 ←2つの配列分の値。 メインはなんとかできたのですが、まだ始めたばかりで配列などの仕組みも基本的なことしか分りません。どのようにしたら2つの配列をひとつの配列に1番目の配列、2番目の配列の順に収める事ができるのでしょうか。キーワードなどのアドバイスよろしくお願いします。

    • ベストアンサー
    • Java
  • 配列で質問があります。

    小さなプログラムを配列を作りました。 3個配列を指定しそのうち2つを返すという ようなプログラムです。 バグがでてしまいメソッドのところで出ます。 Hairetu.java:9: ';' がありません。 int[] hairetu2(int box[0],int box[1]){  エラー1 作成したプログラムは以下です。メソッドの定義など見てみたのですがなぜバグが出るのかよくわかりません。教えて下さいませんか。 class Hairetu{ public static void main (String args[]){ int[] box = new int [3]; box [0] =1; box [1] =2; box [2] =3; int[] hairetu2(int box[0],int box[1]){ return box; } hairetu2 = hairetu2(box[0],box[1]); System.out.println(box); } } ^

    • ベストアンサー
    • Java
  • 無名配列の作成方法について質問

    以下はJavaの参考書の問題集に掲載されていた、無名配列を作成するソースコードです。 この書き方について疑問があるので、質問させて頂きます。 int[][]n=new int[2][]; n[0]=new int[3]; このn[0]=new int[3];が、無名配列を使って要素に値を設定していると解説に書かれていました。 しかし、この参考書では、別のページで無名配列の作成方法として、int[]n; n=new int[]{1,2,5};のように、要素リストを代入する書き方が、無名配列の例として 紹介されていました。。 質問1:何故、n[0]=new int[3];の書き方も無名配列なのですか? 質問2:そもそも「無名配列」とは何ですか?参考書にもネットで調べても その解説がほとんど無かったので、、、

    • ベストアンサー
    • Java
  • 配列表記について

    質問させてください。 以前から気になっていたのですが、 配列を宣言するときに int型の場合  int num[] = new int[5]; と宣言するのにたいして String型(インスタンス)の場合  String[] str = new String[5]; と一般的に書くのはどうしてなのでしょうか? ちなみにどちらでもコンパイルとおりますよね。

    • ベストアンサー
    • Java
  • ポインタと配列 助けてください

    #include <stdio.h> int main(void) { int a[5] = {1, 2, 3, 4, 0}; int i, *ptr; ptr = ######; while (*ptr != 0){ ######; ######; }      for (i = 0; i < 5; i++) printf("a[%d]=%2d &a[%d]=%p\n", i, #####,i, #####); putchar('\n'); ptr = ######; for (i = 0; i < 5; i++){ printf("ptr値 =%d ptrアドレス =%p \n", ####, ####); ####; } printf("\n"); return (0); } 一次元配列a[]の一番目の要素以外を0にするプログラム(ただし、最後の要素は0)を作成したいのですが、#の部分に何をあてはめたらいいかわかりません。 助けてください。

専門家に質問してみよう