• ベストアンサー

この警告はどうすれば?

以下のメソッドを含むプログラムをEclipseで作成している際に次のような警告が発生しました。 型の安全性:型Comparator の式は、未検査の型変換を使用してComparator<? super T>に準拠するようにする必要があります。 型の安全性:型 Arrays の総称メソッド sort(T[], Comparator<? super T>)の未検査の呼び出し sort(Object[],Comparator)がありました。 コンパイルして実行する分には、なんら問題ないのですが、この警告の意味と解決策が分からないままにしておくのは気持ち悪いので、分かる方がいらしたら教えてください。 static void sortName(){  String array[] = new String[4];  array[0] = "abba";  array[1] = "abab";  array[2] = "aaaa";  array[3] = "aabb";  Comparator asc = new Comparator() {   public int compare(Object obj0, Object obj1) {    String nameKana0 = (String)obj0;    String nameKana1 = (String)obj1;    int ret = 0;    ret = nameKana0.compareTo(nameKana1);    return ret;  }  };  Comparator comparator = asc;  Arrays.sort(array, comparator); // 配列をソート  for (int i = 0; i < array.length; i++)   System.out.println(array[i]); }

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

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

  • ベストアンサー
  • asock
  • ベストアンサー率70% (7/10)
回答No.2

#1さんの通り、SDK1.4に戻せば警告は発生しなくなります。 そもそも、JDK 5.0 から何故このような警告が発生するようになったかを考えてみます。 Comparator匿名クラス内のcompare()メソッド内で引数Object obj1, obj2 を(String)にキャストしていますよね。しかし、これがもしString型で無い場合はどうなるでしょう。 例えば、Arrays.sort(array, comparator); のarrayが String[] ではなく、極端な話 Integer[] の場合です。 IntegerはObjectを継承しているので構文的にも間違いはなく、コンパイルも問題なく通りますがおそらく実行時にIntegerインスタンスをStringにキャスト出来ず、Cast関係の例外が発生します。 このような現象を回避するのがGenericsです。 Comparatorの匿名クラスを作成する際に、「何(のオブジェクト)に関するComparatorなのか」をコンパイラに教えてやるわけです。そうすることで誤って型の一致しない配列を渡してやってもコンパイルの時点で 検出することが出来ます。 警告を発しないように対処したコードは以下の用になります。 import java.util.*; public class Test {  public static void sortName(){  String array[] = new String[4];   array[0] = "abba";   array[1] = "abab";   array[2] = "aaaa";   array[3] = "aabb";   Comparator<String> asc = new Comparator<String>() {    public int compare(String obj0, String obj1) {     return obj0.compareTo(obj1);    }   };   Comparator<String> comparator = asc;   Arrays.sort(array, comparator); // 配列をソート   for (int i = 0; i < array.length; i++)    System.out.println(array[i]);  }  public static void main(String[] argv) {   Test.sortName();  } } Genericsの別の利点としていちいちキャストしなくてもよくなることがあげられます。 Vector や ArrayList 等を使うときにも何かと便利です。 ArrayList<String> aryString = new ArrayList<String>(); for (int i=0; i<10; i++)  aryString.add("No." + i); for (int i=0; i<aryString.size(); i++)  System.out.println ( aryString.get(i) ); // キャスト無しで使える

参考URL:
http://www.javaworld.jp/technology_and_programming/-/18161.html
marucha
質問者

お礼

大変分かりやすく説明していただきありがとうございます。 おかげで分からない箇所がわかりました。ありがとうございます。

その他の回答 (1)

  • PED02744
  • ベストアンサー率40% (157/390)
回答No.1

JDKのバージョンを1.5から1.4以下に落とせばエラーは消えるとおもいます。 JDK1.5(JAVA 5.0)から導入されたGenerics により、Object型を使うことによる「何でもOK」を認めない仕様になっています。 必ずString型の変数しか入れないコンパレータならば、 <String>宣言してあげればよろしいかと。

参考URL:
http://journal.mycom.co.jp/column/java/021/

関連するQ&A

  • 多次元配列のソートがうまくいかない

    多次元配列のソートがうまくいかない 質問失礼します. 以下のような,String型,int型,double型の混在した多次元配列([3][3]の配列)をソートするプログラムを作成しました. このプログラムでは3番目の項目でソートを行っています. 問題点なのですが, 3番目の項目がdouble型の一桁(例えばarray[1][2]が2.0)ならばうまくソートできるのですが, 一つを2桁(例えばarray[1][2]を10.0)にすると何故か先頭の数(10.0の場合1)を基準にソートされてしまっているようです・・・ 配列へのデータの入れ方が間違っているのでしょうか? 原因がはっきりわからず困っているのですが, わかる方いましたらよろしくお願いします. public class Sort_test { /** * @param args */ public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ String[][] array = new String[3][3]; array[ 0 ][ 0 ] = "A"; array[ 0 ][ 1 ] = 2001+""; array[ 0 ][ 2 ] = 9.0+""; array[ 1 ][ 0 ] = "B"; array[ 1 ][ 1 ] = 1001+""; array[ 1 ][ 2 ] = 2.0+""; array[ 2 ][ 0 ] = "C"; array[ 2 ][ 1 ] = 3001+""; array[ 2 ][ 2 ] = 6.0+""; TheComparator comparator = new TheComparator(); // 3番目の項目でソートするように設定 comparator.setIndex( 2 ); // ソート実施 Arrays.sort( array, comparator ); dump(array); } public static void dump( String[][] array ) { for ( int i = 0;i < array.length;i++ ) { for ( int j = 0; j < array[ i ].length;j++ ) { System.out.print( "\t" + array[ i ][ j ] ); } System.out.println(); } } } //多次元配列ソート用クラス class TheComparator implements Comparator { /** ソート対象のカラムの位置 */ private int index = 0; /** ソートするためのカラム位置をセット */ public void setIndex( int index ) { this.index = index; } public int compare( Object a, Object b ) { String[] strA = ( String[] ) a; String[] strB = ( String[] ) b; return ( strA[ index ].compareTo( strB[ index ] ) ); } }

    • ベストアンサー
    • Java
  • ComparableとComparatorの違いについてわからなくて困っています。

    ComparableとComparatorの違いについてわからなくて困っています。 以下のURLのサイトを記事を見ているのですが、 http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000179.html http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000180.html java.lang Comparableインタフェース メソッド public int compareTo(Object o) java.util Comparatorインタフェース メソッド public int compare(Object o1, Object o2) public boolean equals(Object obj) これらの違いについてなのですが、URLの記事では、 ・Comparableインターフェイスの実装クラスにしてcompareTo()メソッドを実装するのは、比較対象が明確であり、比較結果が一般的に分かりやすく容易に想像できる場合にのみとした方がよい ・Comparatorは任意の順番でソートしたい場合にも使用できる。例えば、昇順ではなく降順でソートしたい場合や、複数のデータを持つクラスについて細かく比較方法する場合 と記事にありますが、説明がうまく解釈できないです。 ・Comparableは主にラッパークラスやStringなどで使用するためのものなのでしょうか?(実装してるからそうだとは思いますが) 比較対照が明確なので compareToのreturn文で 除算するだけで可能? ・ComparatorはArraysやコレクション、自作クラス向けに任意の順番でソートするためのものなのですか? 自作クラスについてはComparableでもcompareTo()をオーバーライドすれば同じことが可能? 通常はComparator実装クラスのcompare()の中にreturn文でcompareTo()を使用しているような気もします。 この方法だとObject型で引数を渡して、int型に変換して比較になると思いますが、 StringだとComparableを実装してるから、戻り値でint型が返るのかな、 public int compare(String s1, String s2) { return s2.compareTo(s1) } つまり、自作クラスはインスタンスフィールドにある基本型やObject型(String, Integerなど)の値を使い、 基本型においては除算を使用し、オブジェクト(Comparableを実装しているもの)に対してはcompareTo()で比較するのでしょうか? (これで解決したような気もしますが) 質問がわかりずらくてすみません。何か解釈の間違いがあればご指摘お願いします。

  • StringクラスのcompareToメソッド

    ArrayListに登録した文字列を五十音順にソートしようと思いComparator を使用して 以下のようなサンプルプログラムを作ってみました。 ところが想定していたような {赤ちゃん、富士山、山口県}とはならず {富士山、山口県、赤ちゃん} というような結果になりました。 compare() の戻り値の部分を return ((String)arg1).compareTo((String)arg0); に変更しても{赤ちゃん、山口県、富士山} となり辞書の並びとは異なる結果になりました。 辞書順に並べるにはなにかよい方法はありますでしょうか。 public class compareTest { public static void main(String[] args) { ArrayList<String> array = new ArrayList<String>(); String a = "赤ちゃん"; String b = "山口県"; String c = "富士山"; array.add(a); array.add(b); array.add(c); for(int i=0;i<array.size();i++) { System.out.println("ソート前=" + array.get(i)); } Collections.sort(array, new testComp()); for(int i=0;i<array.size();i++) { System.out.println("ソート後=" + array.get(i)); } } } public class testComp implements Comparator { public int compare(Object arg0, Object arg1) { return ((String)arg0).compareTo((String)arg1); } }

    • ベストアンサー
    • Java
  • ソート Comparator

    Integer型の変数num(10,4,8,6,9,5)をそれぞれ含むオブジェクト配列aryがあり、それをソートするため Arrays.sort(arry,sortLogic); とした場合、 Comparatorインターフェースを実装したクラスsortLogic内のメソッドで public int compare(Object object1, Object object2) {   return ((ary)object1).compareTo(((ary)object2).num); } とすると、昇順にソート(修正ソートマージ)、また、 return ((ary)object1).compareTo(((ary)object2).num); とすると降順にソートされるみたいなのですが、どのような手順(アルゴリズム)でソートされるのでしょうか?

    • ベストアンサー
    • Java
  • HashMapデータの並び替えについて

    ファイル名とファイルサイズの複数の組み合わせが入ったHashMap型のインスタンスをファイルサイズ降順に並び替えるコードにおいて、Eclipse上で警告が表示されます。 対処法をお教え頂けませんでしょうか。 〔コード〕 Map<String,Long> filesMap = new HashMap<String,Long>(); (ファイル名とファイルサイズをfilesMapに入れる) // filesMapをファイルサイズの降順に並べる List<Map.Entry<String,Long>> filesEntries = new ArrayList<Map.Entry<String,Long>>(filesMap.entrySet()); Collections.sort(filesEntries, new Comparator(){  public int compare(Object o1, Object o2){   Map.Entry e1 =(Map.Entry)o1;   Map.Entry e2 =(Map.Entry)o2;   return ((Long)e2.getValue()).compareTo((Long)e1.getValue());  } }); 〔警告〕 (Collections.sort(filesEntries, new Comparator(){ 行) この行に複数マーカーがあります - 型の安全性: 型 new Comparator(){} の式は、未検査の型変換を使用して Comparator<? super Map.Entry<String,Long>> に準拠するようにする必要があります - 型の安全性: 型 Collections の総称メソッド sort(List<T>, Comparator<? super T>) の未検査の呼び出しsort(List<Map.Entry<String,Long>>, new Comparator(){}) がありました - Comparator は raw 型です。総称型 Comparator<T> への参照は、パラメーター化する必要があります (Map.Entry e1 =(Map.Entry)o1; 行) (Map.Entry e2 =(Map.Entry)o2; 行) この行に複数マーカーがあります - Map.Entry は raw 型です。総称型 Map<K,V>.Entry<K,V> への参照は、パラメーター化する必要があります - Map.Entry は raw 型です。総称型 Map<K,V>.Entry<K,V> への参照は、パラメーター化する必要があります 2012 Feb. 04.

    • ベストアンサー
    • Java
  • C#のListの要素がHashtableの並べ替え

    Listの要素がHashtableなのですが、Hashtableの特定のキーでListを並べ替える事ができるでしょうか? 例えば次の様な場合 int[] pid = new int[] { 2, 1, 3 }; string [] pname = new string[] { "田中", "鈴木", "本田" }; string[] pref = new string[] { "埼玉", "群馬", "千葉" }; int[] presult = new int[] { 65, 38, 52 }; List<object> usertList = new List<object>(); for (int i = 0; i <= 2; ++i) { Hashtable t_obj = new Hashtable(); t_obj["pid"] = pid[i]; t_obj["pname"] = name[i]; t_obj["pref"] = pref[i]; t_obj["presult"] = presult[i]; usertList.Add(t_obj); } usertListを pidに従って並べ替える presultに従って並べ替える presultとpidに従って並べ替える という事を行いたいのですが、どうすればよいか分かりません。 申し訳ありませんが、教えていただけないでしょうか?

  • Comparatorを使用したソートについて

    Javaのバージョンは1.5です。 Comparatorを使用してソートを行っています。 ソートをシフトJISコード順とするため 下記のようなクラス、メソッドを作成しています。 public class ExmComparator implements Comparator<Object> { public int compare(Object obj1, Object obj2) { byte[] b1 = obj1.toString().getBytes("SJIS"); byte[] b2 = obj2.toString().getBytes("SJIS"); int len; if (b1.length < b2.length) { len = b1.length; } else { len = b2.length; } int s1h, s2h; for (int i = 0; i < len; i++) { s1h = b1[i]; s2h = b2[i]; if (!(s1h == s2h)) { return s1h - s2h; } } return b1.length - b2.length; } } ソートするキー(名称+コード)が "-0001","テレビ0002","電話0003","PC0004"の場合はシフトJISコードの昇順に "-0001","PC0004","テレビ0002","電話0003"としたいのですが、 "テレビ0002","電話0003","-0001","PC0004"とソートされてしまいます。 半角ハイフンは名称がない場合の代替名称です。 シフトJISコードは - :0x002d P :0x0050 テ:0x30c6 電:0x9364 なのでこの通りにソートされるのではないかと思ったのですが、 2バイト文字はどうなんでしょうか…。

    • ベストアンサー
    • Java
  • SAStrutsでActionからJSPに値を渡す

    はじめまして、当方駆け出しのプログラマです。 JAVA歴2ヶ月で勉強(研修)させてもらっています。 初歩的な質問かもしれませんが、ご返答いただけると幸いです。 勉強して一ヶ月ほどでJSPサーブレットを使った簡単なスケジュールを表示するプログラムを作りました。環境はEclipse(pleiades3.5)+tomcat6.0+jre1.6+mysql5.5.10です。 これをフレームワークに準拠したつくりに移行してくれと上司の方に言われました。 しかし、私が作ったものは、スケジュール表示で日付で参照し、そこからデータベースからとったスケジュールの日付と合致するものがある場合リンクを表示するというものでした。 このためタグライブラリのC:each等の繰り返しは使えないため、スクリプトレットで変数として値を持ってこないと動作しない状態です。 Stringやint型はrequest.getAttributeでもってこれるのはわかったのですがentityに入っている値を持ってくることが出来ずNullになってしまいます。 ソースはこちらになります。 書き出しで説明すると。 DB接続→値を持ってきてentityにセットする→これらをarrayListに格納→arrayListの中身を日付順にソート→entityの配列に収納する→jspに受け渡し→表示できない。 という状況です。 ScheduleMainはentityでSchedule_mainはDBのテーブルです。arrayの部分で日付順になるようにソートをかけてあります。これは理由があってsql内でソートしていません。 scheduleitemsはScheduleItemsというentityで複数個スケジュールを保管できるように配列をゲッターセッター設置してあります。  Action.java for(int i=0 ; i<schedulemain.size();i++){ ScheduleMain schemain = schedulemain.get(i); int ID = schemain.getId(); String place = schemain.getPlace(); String schedule = schemain.getSchedule(); int empId = schemain.getEmpId(); int category = schemain.getCategory(); int scheCategory = schemain.getScheCategory(); Date scheduleDay = schemain.getScheduleDay(); Time endtime = schemain.getEndtime(); Time starttime = schemain.getStarttime(); schedule_main.setCategory(category); schedule_main.setEmpId(empId); schedule_main.setEndtime(endtime); schedule_main.setId(ID); schedule_main.setPlace(place); schedule_main.setScheCategory(scheCategory); schedule_main.setSchedule(schedule); schedule_main.setScheduleDay(scheduleDay); schedule_main.setStarttime(starttime); array.add(schedule_main); } ScheduleMain[] itembean = (ScheduleMain[])array.toArray(new ScheduleMain[array.size()]); Comparator asc = new Comparator() { public int compare(Object obj0, Object obj1) { String nameKana0 = ((ScheduleMain) obj0).getScheduleDay().toString(); String nameKana1 = ((ScheduleMain) obj1).getScheduleDay().toString(); int ret = 0; // カナの昇順 if ((ret = nameKana0.compareTo(nameKana1)) == 0) { // カナが同じ場合はIDの昇順 String id0 = ((ScheduleMain) obj0).getStarttime().toString().substring(0,5); String id1 = ((ScheduleMain) obj1).getStarttime().toString().substring(0,5); ret = id0.compareTo(id1); } return ret; } }; scheduleitems.setItembean(itembean); jsp側ですが。 ScheduleItems scheduleitems = (ScheduleItems)request.getAttribute("Scheduleitems"); で宣言をし、out.printやlengthをとってもnullExeprionになってしまいます。 enteity部分 ScheduleItems.java package schedule.entity; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name="schedule_main") public class ScheduleItems { public ScheduleMain[] itembean = null; public ScheduleItems(){ } public ScheduleMain[] getItembean() { return itembean; } public void setItembean(ScheduleMain[] itembean) { this.itembean = itembean; } } ScheduleMainは自動生成されるDoltengでDBから生成しました。 entityではだめなのかと思いDtoでも試しましたがやはり同じ症状になってしまいます。 この部分が解決されるだけでかなりの進捗が期待されるのでどうかよろしくお願い致します。 長文失礼しました。よろしくお願い致します。

    • ベストアンサー
    • Java
  • compareToについて

    質問なのですが、 package projecjava4t; import java.util.Arrays; /** * Program の概要の説明です */ public class Program { public static void main(String[] args) { Girl[] a=new Girl[4]; a[0] = new Girl("candy", 100); a[1] = new Girl("Lisa", 1010); a[2] = new Girl("Ann",1020); a[3] = new Girl("Eliza",1030); Arrays.sort(a); int i; for(i=0;i<a.length;i++)   a[i].disp(); } } class Girl implements Comparable { String name; int age; public Girl(String s, int a){ name = s; age = a; } public void disp(){ System.out.println("名前"+name+"年齢"+age); } public int compareTo(Object g){ return -(age - ((Girl)g).age); } } のArrays.sort(a)のcompareTo(Object g)では、どのようなことが起きてるのかわかりません。 あと、-(age - ((Girl)g).age)の意味がよくわからないのですが、 わかる方いらしたらご教授よろしくお願いします。

    • ベストアンサー
    • Java
  • Stringの値で型キャストしたい(Java)

    最近OKWaveでお世話になっています。 表現がおかしいかもしれませんが、Stringの変数の値を使って、型キャストしたいです。 様々なオブジェクトが入る配列(Vector)を使用しているため、VectorをObject型にして使用しています。 配列のある要素をget()したのち、getClass().getSimpleName()でクラス名を取得し、そのクラス名を、 Object obj = array.get(i); String name = obj.getClass().getSimpleName(); if(name.equal("Integer")) {  method((Integer)obj);   ・   ・   ・ のような形で、場合分けして、メソッドを呼び出しています。 ですが、この方法だと、条件分岐が増えて、見づらいです。 そこで、クラス名を取得したnameをうまく使ってobjを型キャストしたいです。 これを解決させる方法もしくはヒントを教えてください!

    • ベストアンサー
    • Java

専門家に質問してみよう