2012-02-14 14 views
1

は、私はいくつかのレガシーコードをクリーンアップし、私はを取り除くためにstruggelingだいくつかのunchecked castの警告を持ってしようとしています。困難な未チェックのキャストの警告

私は以下のコンパイルプログラムに警告を与えるコードを抽出しました。私はそれを小さくするために多くのコードを削除したので、すべてが完全に意味をなさないかもしれないことに注意してください。それはコンパイルされますが、実行すると何もしません。上記のコードをコンパイル

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipException; 
import java.util.zip.ZipInputStream; 

public class GenericsTest { 

    public static void main(String[] args) throws IOException { 
     Reader reader = new Reader(); 
     List<String> stringEntries = reader.readAll(StringEntry.class); 
    } 

    public static class Reader { 

     public <T> ZipInputStream getInputStream(String fileName) throws ZipException, FileNotFoundException { 
      return new ZipInputStream(new FileInputStream(fileName));//_file.getInputStream(_paths.get(fileName)); 
     } 

     public <T, TEntry extends Entry<T>> List<T> readAll(Class<TEntry> type) throws IOException { 
      List<T> list = new ArrayList<T>(); 
      List<TEntry> entries = createEntries(type); 
      for (TEntry entry : entries) { 
       list.add(read(entry)); 
      } 
      return list; 
     } 

     public <T> T read(Entry<T> entry) throws IOException { 
      ZipInputStream is = null; 
      try { 
       //is = _archive.getInputStream(entry.getName()); 
       return entry.read(is); 
      } finally { 
       if (is != null) { 
        is.close(); 
       } 
      } 
     } 

     public <TEntry extends Entry> List<TEntry> createEntries(Class<TEntry> type) throws ZipException { 
      List<TEntry> entries = new ArrayList<TEntry>(); 
      List<String> paths = new ArrayList<String>();//getPaths(type); 
      for (String path : paths) { 
       entries.add(createEntry(type, path)); 
      } 
      return entries; 
     } 

     public <TEntry extends Entry> TEntry createEntry(Class<TEntry> type, String folder) { 
      if (StringEntry.class.equals(type)) { 
       return (TEntry) new StringEntry(folder); 
      } else if (IntegerEntry.class.equals(type)) { 
       return (TEntry) new IntegerEntry(folder); 
      } 
      throw new IllegalArgumentException("Unknown type: " + type); 
     } 
    } 

    public static abstract class Entry<T> extends ZipEntry { 

     private T _data; 

     public Entry(T data, String folder, String name) { 
      super(folder + "/" + name); 
      _data = data; 
     } 

     protected abstract T read(InputStream is) throws IOException; 
    }; 

    public static class StringEntry extends Entry<String> { 

     public StringEntry(String folder) { 
      super("Hallo world!", folder, "StringEntry"); 
     } 

     @Override 
     protected String read(InputStream is) throws IOException { 
      throw new UnsupportedOperationException("Not supported yet."); 
     } 
    }; 

    public static class IntegerEntry extends Entry<Integer> { 

     public IntegerEntry(String folder) { 
      super(42, folder, "IntegerEntry"); 
     } 

     @Override 
     protected Integer read(InputStream is) throws IOException { 
      throw new UnsupportedOperationException("Not supported yet."); 
     } 
    }; 
} 

public <TEntry extends Entry<T>> TEntry createEntry... 

にコンパイラエラー(cannot find symbol: class T)を

public <TEntry extends Entry> TEntry createEntry... 

を与える変更次の警告

GenericsTest.java:57: warning: [unchecked] unchecked cast 
found: GenericsTest.StringEntry 
required: TEntry 
       return (TEntry) new StringEntry(folder); 
GenericsTest.java:59: warning: [unchecked] unchecked cast 
found: GenericsTest.IntegerEntry 
required: TEntry 
       return (TEntry) new IntegerEntry(folder); 
2 warnings 

を与えます。

それが正常に動作しているので、私はあまりにも多くのコードを変更したくないので、どのように私は、少なくともコードの変更と警告(隠せない)修正できますか?複数の一般的なパラメータを使用したい場合は

答えて

2

を...ただ、それを変更、TODO時にあなただけのJava 5に移行している私は念のために言っている

をつまずくと警告の数千を持っていますメソッドを使用するだけですClass.cast()

public <TEntry extends Entry<?>> TEntry createEntry(Class<TEntry> type, String folder) { 
    if (StringEntry.class.equals(type)) { 
     return type.cast(new StringEntry(folder)); 
    } else if (IntegerEntry.class.equals(type)) { 
     return type.cast(new IntegerEntry(folder)); 
    } 
    throw new IllegalArgumentException("Unknown type: " + type); 
} 

上記の変更により、私のための警告なしにコードがコンパイルされます。

また、getInputStream()の署名の<T>はおそらく必要ありません。

+0

私はしませんでしたClass.cast()について知っている!毎日何か新しいことを学ぶ:)ありがとう! – ughzan

+0

@ughzan Class.cast()は、チェックされていないキャストの警告を取り除く方法の主な方法です。その主な制限は、 'Entry '(これを拡張する 'StringEntry'クラスではなく)のクラスオブジェクトを持つことができないため、キャストできません。 – millimoose

2

あなたはパラメータリストで指定する必要があります。これを試すことができますか?レガシーコードのための

public <T, TEntry extends Entry<T>> List<TEntry> createEntries(Class<TEntry> type) throws ZipException { 
     List<TEntry> entries = new ArrayList<TEntry>(); 
     List<String> paths = new ArrayList<String>();//getPaths(type); 
     for (String path : paths) { 
      entries.add(createEntry(type, path)); 
     } 
     return entries; 
    } 

    public <T, TEntry extends Entry<T>> TEntry createEntry(Class<TEntry> type, String folder) { 
     if (StringEntry.class.equals(type)) { 
      return type.cast(new StringEntry(folder)); 
     } else if (IntegerEntry.class.equals(type)) { 
      return type.cast(new IntegerEntry(folder)); 
     } 
     throw new IllegalArgumentException("Unknown type: " + type); 
    } 
} 
+0

あなたは実際には、コンパイラの警告が離れて行かせるかどうかを確認するためにこれを試していましたか? – millimoose

+0

元の答え:いいえ。更新答えは(JDK 1.6) – gpeche

+0

私のためにコンパイル 'T'は、更新に冗長であるが、それは単なる揚げ足取りです。 – millimoose

0

私見、それは一般的な友好可能にするために:

public <T, TEntry extends Entry<T>> TEntry createEntry(... 

UPDATE

私はこれで遊ぶと、使用中にそれらの素敵なクラスオブジェクトを置くためにいくつかの時間を持っていましたかなりの経験、特にあなたがコードの大きな基盤を持っているならば...おそらくこのコードが配備されているので、あなたは反復的なアプローチを考慮しませんか?

反復的なアプローチでは... @SuppressWarningを使用してすべての警告を取得し、TODOアノテーションを使用してそれらを削除します。時間が経過すると、コードを変更する必要があるたびにあなたは既ににClassオブジェクトを渡している。..

+0

'@ SuppressWarnings'は、正しくカプセル化されたハックの最後の手段です。正しいものであることがわかっていれば、正しいままであることを確認するテストを行うことが好ましく、クリーンで警告を取り除くことができないことがわかっているとき少なくともそれ以上の価値はありません。**あなたがコードベースの周りに自由に振りかけることで、コンパイラがあなたに罪悪感を感じさせないようにするためのものではありません。 – millimoose

+0

私はあなたに完全に同意します... Java 5に移行する従来のプロジェクトを行っている場合、ちょうど正しいジェネリックを手に入れるのが手間がかからない場合に話していただけです。 @SuppressWarningは受け入れられるでしょう –

+0

その場合、私は警告を残すだけです。 – millimoose