• 締切済み

javaのGenericsが良く分かりません

かなり以前に java プログラミングを少しばかりやっていたので java は少し分かるのですが、最近 また java プログラミング始めてみたのですが、Generics なる機能が「Java SE5.0から導入されたようですが、良く分かりません。 ご存知の方がいらしたら どうか ご教授下さいませm(_ _)m 開発環境 eclipse java 8 class Box<T> { // Object obj; T obj; @SuppressWarnings("unchecked") public T getT(){ return obj; } public void setT(T o){ obj = o; } @SuppressWarnings("unchecked") public void setTExtends(Box<? extends T> o){ obj = (T)o; } } Box<Number> boxN = new Box<Number>( ); Box<Integer> boxI = new Box<Integer>( ); boxN.setT((Number)new Integer(1)); // 当然、正常にコンパイルされる。 boxN.setT(new Integer(1)); // なぜか正常にコンパイルされる。 boxN.setT(boxN.getT()); // 正常にコンパイルされる。 boxN.setT(boxI.getT()); // なぜか正常にコンパイルされる。 boxN.setTExtends((Number)new Integer(1)); // なぜかコンパイル・エラーになる。 boxN.setTExtends(new Integer(1)); // なぜかコンパイル・エラーになる。 boxN.setTExtends(boxN.getT()); // なぜかコンパイル・エラーになる。 boxN.setTExtends(boxI.getT()); // なぜかコンパイル・エラーになる。 boxI.setT(new Integer(1)); // 当然、正常にコンパイルされる。 boxI.setT(boxI.getT()); // 当然、正常にコンパイルされる。 boxI.setTExtends(new Integer(1)); // なぜかコンパイル・エラーになる。 boxI.setTExtends(boxI.getT()); // なぜかコンパイル・エラーになる。

  • Java
  • 回答数1
  • ありがとう数2

みんなの回答

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.1

「なぜかコンパイル・エラーになる。」とコメントに書かれてる箇所は、あなたがそう思われてるだけで極当然にエラーになるものです。 BoxクラスのsetTExtends(Box<? extends T> o)メソッドの引数の型は、Box<? extends T>なのですから(Boxクラスの変数としてBox<Number>で宣言したときにはTがNumberに置き換わりBox<? extends Number>になりますし、Box<Integer>で宣言したときにはBox<? extends Integer>になります)、 そこに派生関係のないNumberクラスやIntegerクラスのインスタンスを渡してもコンパイラはコンパイルしようがありません。 >boxN.setT(new Integer(1)); // なぜか正常にコンパイルされる。 >boxN.setT(boxI.getT()); // なぜか正常にコンパイルされる。 boxNの型はBox<Number>ですから、setTメソッドの引数の型はNumberです。 new Integer(1)の型はIntegerで、IntegerはNumberの派生クラスです。 boxlの型はBox<Integer>ですから、getTメソッドの戻り値の型はIntegerです。 どこかコンパイルエラーになる要素ありますか?

amanojaku1
質問者

お礼

返信ありがとう御座います。 > そこに派生関係のないNumberクラスやIntegerクラスのインスタンスを渡してもコンパイラはコンパイルしようがありません。 その辺からして良く理解できていなかったと言うことです。 > boxNの型はBox<Number>ですから、setTメソッドの引数の型はNumberです。 > new Integer(1)の型はIntegerで、IntegerはNumberの派生クラスです。 > boxlの型はBox<Integer>ですから、getTメソッドの戻り値の型はIntegerです。 > どこかコンパイルエラーになる要素ありますか? Generics を使う場合(かつワイルドカードを使わない場合)は同一の型でなければならない、と言う記述から、通常のオブジェクト型も制限されるのかと勘違いしておりました。 こちらでも、イロイロやってみて、分かりました。 (自分的な表現になりますが)仮型パラメータ「T」は Element(要素) に対する宣言、「Box<?extends T>」はElement(要素)対する宣言と言う感じでしょうか。 つまり、この変の区別が全く分かってなかったと言う事です。

amanojaku1
質問者

補足

訂正 > (自分的な表現になりますが)仮型パラメータ「T」は Element(要素) に対する宣言、「Box<?extends T>」はElement(要素)対する宣言と言う感じでしょうか。 (自分的な表現になりますが)仮型パラメータ「T」は Element(要素) に対する宣言、「Box<?extends T>」はContainer(容器)に対する宣言と言う感じでしょうか。

関連するQ&A

  • java applet

    import java. applet.*; import java. awt. Button; import java. awt. Label; import java. awt. TextField; import java. awt. event.*; public class 1120 extends Applet implements ActionListener { private TextField box1 = new TextField(5); private TextField box2 = new TextField(5); private TextField box3 = new TextField(5); private Label moji1 = new Label(" と "); private Label moji2 = new Label(" の和は "); private Label moji3 = new Label(" である。 "); private Button ok = new Button("OK"); public void init() { resize( 320 , 240); add( box1 ); add( moji1 ); add( box2 ); add( moji2 ); add( box3 ); add( moji3 ); add( ok ); ok.addActionListener( this ); } public void actionPerformed( ActionEvent e ) { int i=0 ,j =0 , k; String t1 = box1.getText(); String t2 = box2.getText(); i = Integer.parseInt( t1 ); j = Integer.parseInt( t2 ); k = i + j; String s = Integer.toString( k ); box3. setText( s ); } } //上記のプログラムを書いたのですが、なぜかエラーが出てしまいます。勿論、自分でも見直しましたが、その理由がわかりませんでした。知識のある方、ご回答の方お願いします。

  • Javaの多態性について質問です

    Java初心者です。どなたかお力をお貸しください。 ------------------- class Animal { public void eat() { // 汎用的なコード } } class Dog extends Animal { public void eat() { // 特化したコード } public void bite() { // Dog特有のコード } } ------------------- 上記のクラスについて質問があります。 Animal obj = new Dog(); obj.bite(); このコードがコンパイルエラーになるのは何故でしょうか? コンパイラが参照型のみをチェックし、Animalクラスにbiteメソッドが 無いため、エラーを出すと参考書に書いてありました。 つまり、スーパークラス型の参照変数にサブクラスのインスタンスを格納し、 サブクラス特有のメソッドをコールできないとはどういう意図なんでしょうか? コンパイラのチェックで引っかかるのは分かったのですが、 オブジェクト指向としては、この使い方は推奨されないということでしょうか? (Animalの参照で、Dog特有のメソッドは使わない?) 実際にJavaでプログラムを組むときには、こんな使い方をしないのですか? 有知識者の方、教えて下さい。 私は、オブジェクト指向の多態性の理解が甘いため、こんな質問をしているのだと 思います。申し訳ございません。

    • ベストアンサー
    • Java
  • 関数型インターフェースの配列の作り方

    関数型インターフェースを勉強し始めた者です。 関数型インターフェースの配列はどのように作ればよいのでしょうか? 関数配列のようなものを作ろうとして以下のプログラムを作りました。 環境:Windows 7 64bit IDE:Eclipse 4.5.2 JDK:1.8 package interfaceSample; import java.util.function.Function; public class FuncSample3 { public static void main(String[] args) { //@SuppressWarnings("unchecked") Function<Integer, Integer>[] funcList = new Function[3]; funcList[0] = FuncSample3::mul; funcList[1] = FuncSample3::add; funcList[2] = FuncSample3::sub; for (Function<Integer, Integer> function : funcList) { funcApply(function, 10); } } public static int mul(int x) { return x * 2; } public static int add(int x) { return x + 2; } public static int sub(int x) { return x - 2; } public static void funcApply(Function<Integer, Integer> func, int t) { System.out.println("この関数の値は"+func.apply(t)); } } このプログラムを打ち込んだところ、期待通りの出力をしてくれたのですが、以下の警告が出てきました。 型の安全性: 型 Function[] の式は、未検査の型変換を使用して Function<Integer,Integer>[] に準拠するようにする必要があります このメッセージでググって見たのですが、インターフェースについてこのメッセージが出たケースに当たりませんでした。 @SuppressWarnings("unchecked")を付ければ警告は消えるのですが、あんまり気分が良くないです。 よろしくお願いいたします。 ※OKWAVEより補足:「Webシステム開発」についての質問です。

    • ベストアンサー
    • Java
  • テキストファイルの日付表示

    JAVA初心者なのですが、テキストファイルに出力する時にファイル名を現在日付にしたいのですが、どうすればよいでしょうか?(yyyymmdd.txtを20070316.txtというふうにしたい) 後、@SuppressWarnings("unchecked")と記述しているのにコンパイルで-Xlint:unchecked.警告が出てきてします!どなたかご教授ください!!ちなみにJAVA1.5 import java.io.File; import java.io.FileWriter; import java.io.BufferedWriter; import java.io.IOException; import java.util.ArrayList; public class Writedown { @SuppressWarnings("unchecked")/*コンパイラの警告を抑制する */ public static void fileWrite(ArrayList<ArrayList> WriteArrayList) { try { File txt = new File("yyyymmdd.txt"); /*出力するファイル*/ BufferedWriter bw = new BufferedWriter(new FileWriter(txt));/* try { for(int i = 0; i < WriteArrayList.size(); i++){ ArrayList list = WriteArrayList.get(i); if(i == 0){ bw.write((list.size() - 3) + "科目成績表\r\n"); } for(int j = 0; j < list.size(); j++){ if(j > 0){ bw.write("\t"); } if(list.get(j).toString().equals("名前")){ list.remove(j); list.add(j,"名前"); } bw.write(list.get(j).toString()); System.out.print(list.get(j) + "\t"); } bw.write("\r\n"); bw.flush(); System.out.println(""); } } catch (IOException e) { System.out.println("ファイル書き込みエラー"); } bw.close(); } catch (IOException e) { System.out.println("ファイルオープンエラー"); } } }

  • javaに関する質問

    n個の整数値を入力し、それらの値を昇順に並べ替えるプログラムを書いたのですがエラーにより問題が発生しました。 問題は下記の実行例のように数字を,で区切り入力すると、エラーが発生し結果が表示されないという問題です。(Enterで改行するように区切ればエラーなく実行されます) 実行例として 整数値を入力してください。 1,5,7,3 ← 手入力部分 1,3,5,7 ← 実行結果 となれば正解のようです。 これが僕の書いたコードです。 package jp.javadrive; import java.util.Arrays; import java.util.Scanner; public class Java { public static void main(String[] args) { System.out.println("整数値を入力してください。"); @SuppressWarnings("resource") Scanner a = new Scanner(System.in); @SuppressWarnings("resource") Scanner b = new Scanner(System.in); @SuppressWarnings("resource") Scanner c = new Scanner(System.in); @SuppressWarnings("resource") Scanner d = new Scanner(System.in); int a1 = a.nextInt(); int b1 = b.nextInt(); int c1 = c.nextInt(); int d1 = d.nextInt(); int[] arr = new int[]{a1,b1,c1,d1}; Arrays.sort(arr); for(int i = 0;i < arr.length;i++) System.out.print(arr[i]); } } 初めてjavaを触った為、ググりながら書いていたので仕組みを分かっていないところがあるので、間違っている箇所があればどしどしご指摘お願いします。

    • ベストアンサー
    • Java
  • javaのsetColor、setBackgroundについて

    プログラミング初心者で、困っています。教えてください。Javaで g.setColor(Color.red); というサンプルに良くあるコードをコンパイルしてもエラーになってしまいます。 import java.applet.Applet; import java.awt.Graphics; public class First2 extends Applet{ public void init() { setBackground(Color.yellow); } } をコンパイルすると C:\myJ\test1>javac First2.java .\Color.java:7: ')' がありません。 g.setColor(Color red); ^ First2.java:6: シンボルを見つけられません。 シンボル: 変数 yellow 場所 : Color の クラス setBackground(Color.yellow); ^ .\Color.java:6: java.awt.Graphics は abstract です。インスタンスを生成することは できません。 Graphics g = new Graphics(); ^ .\Color.java:7: シンボルを見つけられません。 シンボル: 変数 Color 場所 : Color の クラス g.setColor(Color red); ^ エラー 4 個 となってしまうんです。 ネット上のいろんなサイトでは問題なく動作するように 書かれていますが、なぜエラーになるんでしょう? どうしたら解決できますか?ご指南下さい。 ちなみにjavaのversion は 1.6 です。

    • ベストアンサー
    • Java
  • JavaのRMIで!!

    クライアントから呼び出してサーバーでhogehogeを表示させるようにこんなプログラムを書きました。 command.javaが以下の内容 import java.rmi.*; interface command extends Remote{ void comcom() throws RemoteException; } commandclient.javaが以下の内容 import java.rmi.*; public class commandclient { public static void main(String args[]) { command obj = null; try { System.setSecurityManager(new RMISecurityManager()); obj = (command)Naming.lookup("rmi://localhost/MyObject"); obj.comcom(); } catch(Exception e) { e.printStackTrace(); } } } commandserver.javaが以下の内容 import java.rmi.*; import java.rmi.server.*; public class commandserver extends UnicastRemoteObject implements command { public static void main(String args[]) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { commandserver obj = new commandserver(); Naming.rebind("MyObject", obj); } catch (Exception e) { e.printStackTrace(); } } public commandserver() throws RemoteException { } public void comcom() throws RemoteException { System.out.println("hogehoge"); } } こんなプログラムを書いてコンパイルして実行したらhogehogeが表示されるかな?と思ったら実効するとなんか意味不明なエラーがでます。これはなぜでしょうか?

  • JAVAのコンパイルについて教えてください。

    public class exam05d { public static void main(String[] args) { int value=args[0]; if(value==0) { System.out.println("valueの値は0"); } else { System.out.println("valueの値は0以外"); } } } 上記のプログラムをコンパイルすると exam05d.java:3: 互換性のない型 検出値:java.lang.String 期待値:int int value=args[0]; というエラーが出てしまいます。 これを正常に動作させるにはどう改良すれば良いか教えて頂けないでしょうか。 また変更を行わなければならない理由も教えていただけると有難いです。 プログラミングを始めたばかりで行き詰っています。 回答お待ちしております。

  • JAVAについて。コンパイルができません

    public class Main { public static void main(String[] args){ System.out.println("Hello World"); } } 上のソースで記述して、コマンドプロンプトでコンパイルしようとすると 下のような表示が起きます C:\Program Files\Java\jdk-12.0.1\bin>javac Main.java Main.java:1 エラー: Mainの書き込み中にエラーが発生しました: C:\Program Files\Java\ jdk-12.0.1\bin\Main.class public class Main { ^ エラー1個 何が原因でコンパイルされないかわからないです。 わかるかたいましたらよろしくお願いします。

  • java

    コンパイルできても、実行ができません。 次のようなエラーがでます。 このエラーはどのようなエラーなのでしょうか? Exception in thread "main" java.lang.NoClassDefFoundError: test コードはただたんにHello JAVA と表示させるだけです。 class Test{ public static void main(String args[]){ System.out.println("Hello Java\n"); } }

    • ベストアンサー
    • Java

専門家に質問してみよう