9

ディスク/ネットワークからオブジェクトを取得するイテレータを実装したいと思います。

Iterator itr = getRemoteIterator();
while(itr.hasNext()) {
    Object element = itr.next();
    System.out.print(element + " ");
}

ただし、問題は、 IteratorhasNext()オブジェクトのnext()メソッドがをスローできないことです。この問題を回避する他の標準インターフェースはありますか?IOException

必要なコードは次のとおりです。

public interface RemoteIterator<E> {
    boolean hasNext() throws IOException;
    E next() throws IOException;
    void remove();
}
4

11 に答える 11

8

それはまさにあなたが望むものではありませんが、考慮してください:

これはネットワーク経由で行われるため、遅くなる可能性があります。Future おそらくa (または同様のもの)を使用しているはずです。

したがって、RemoteIterator<E>wherenext()が E を返す代わりに、次を使用します。

RemoteIterator<Future<E>>を返しますFuture<E>

このメソッドでは、anyを でFuture.get()ラップできます。IOExceptionExecutionException

完璧ではありませんが、動作Future.get()が遅くなる可能性があることを暗示しています。さらに、他のプログラマーに何が起こっているかを知らせるチェック例外をスローしgetCause()、自然な応答は を呼び出すことです。したがって、これにより、ほとんどの「WTF」の側面が回避されます。

于 2012-10-16T19:40:48.097 に答える
8

残念ながら、これはできません。宣言された例外はメソッドのシグネチャの一部であり、たとえばそれらを絞り込むことができます

interface FooCallable extends Callable<T> {
T call() throws IOException; // Narrows Exception from the parent interface
} 

新しい throws 句を導入したり、宣言された句を拡張したりすることはできません。

Iteratorは基本的な Java インターフェースであり、enhanced for によって使用されます。

for (T obj: ioExceptionThrowingIterable) { ... }

チェックIOExceptionをキャッチまたはスローする必要があります。

RuntimeException意見の問題ですが、カスタム サブクラスを使用し、インターフェイスを慎重に文書化する必要があると思います。チェック例外は、それに関連する問題があるため、Spring などの最新のフレームワークでは回避されています。

編集: user949300 の回答から借用して適用すると、返されたオブジェクトを次のようにラップできます。

interface RemoteObject<T> {
    T get() throws IOException
}

次に を返し、でアンラップするときにIterator<RemoteObject<T>>呼び出し元に を処理させます。IOExceptionget

for (RemoteObject<Foo> obj: iterable) {
    try { 
       foo = obj.get()
    } catch (IOException ex) { 
    /*
     * 9 times out of 10, the lazy user just prints the stack trace 
     * or something else inappropriate
     * which is why I despise checked exceptions
     */
    }
}

この場合、拡張する必要はなくIterator、直接使用できます。実際、Collection該当する場合は を使用できます。

于 2012-10-13T15:19:39.733 に答える
3

Next() はhttp://docs.oracle.com/javase/7/docs/api/java/util/NoSuchElementException.htmlをスローしています。カスタム Exception クラスを記述して、その例外をキャッチし、IOException をスローできます。

于 2012-10-09T14:06:17.610 に答える
1

これが私の貢献であり、スタックの一番下にあります。

それは本当にあなたが望むものではありませんが、それは近いです。

public class IOIterator<E>
   implements
      Iterator<E>
{
   @Override
   public boolean hasNext()
   {
      return index < 5;
   }

   @Override
   public E next()
   {
      try
      {
         if( index++ > 3)
         {
            throw new IOException( "True fault origin" );
         }
      }
      catch( Throwable t )
      {
         NoSuchElementException nse = new NoSuchElementException( "index: " + index );
         nse.initCause( t );
         throw nse;
      }
      return null;
   }

   @Override
   public void remove()
   {
      if( index == 0 ) throw new IllegalStateException( "call next first!" );
      try
      {
         if( index == 4 )
         {
            throw new IOException( "True fault origin" );
         }
      }
      catch( Throwable t )
      {
         UnsupportedOperationException uoe = new UnsupportedOperationException( "index: " + index );
         uoe.initCause( t );
         throw uoe;
      }
   }

   private int index;



   public static void main( String[] args )
   {
      IOIterator<Socket> it = new IOIterator<>();
      while( it.hasNext())
      {
         Socket socket = it.next();

      }
   }

}

そして、例外スタック トレース:

Exception in thread "main" java.util.NoSuchElementException: index: 5
    at hpms.study.IOIterator.next(IOIterator.java:32)
    at hpms.study.IOIterator.main(IOIterator.java:67)
Caused by: java.io.IOException: True fault origin
    at hpms.study.IOIterator.next(IOIterator.java:27)
    ... 1 more
于 2012-10-13T15:33:06.083 に答える
1

Iterator はよく知られている設計パターンです。SDK イテレーターが現在のニーズに合わない場合は、自分でイテレーターを作成できます。

このサイトで素敵な説明とサンプル コードを見つけました。そのコードを参考にして、必要な Iterator Interface の独自の実装を作成できます。

于 2012-10-13T13:03:23.177 に答える
1

基本的な問題は、そうするように設計されていない API を介してチェック例外をスローできるようにしたいということです。

黒魔術なしでこれを機能させる唯一の正当な方法は、未チェックの例外でラップすることです。最も単純なのは RuntimeException です。

} catch (IOException e) {
   throw new RuntimeException("failed in " + fileName, e);
}

その後、呼び出し元のコードで RuntimeException をキャッチし、getCause()メソッドを確認できます。

これが例外であることを明示的に伝える必要がある場合は、委譲する必要があるコンストラクターを作成して実装することを検討してください。その後、代わりに FooBarException をキャッチして、上記のように処理できます。FooBarDomainException extends RuntimeExceptionsuper(...,e)getCause()

これを行うために魔法を使用しないことをお勧めします。魔法が壊れると、見つけて修正するのが難しい非常に非自明な方法で発生する傾向があります。さらに、他の人が維持するのが難しくなります。

于 2012-10-13T13:14:24.973 に答える
1

オブジェクトの取得はメソッド内で行われるため、 getRemoteIterator() メソッドは理想的には IOException をスローすることをお勧めします。

于 2012-10-13T12:42:58.437 に答える
0

この問題にはもう1つのアプローチがあります。主なアイデアは拡張することNoSuchElementExceptionです:

class RemoteIOException extends NoSuchElementException {
    ...
}

欠点は、をNoSuchElementException拡張することRuntimeExceptionです。

于 2012-10-16T21:37:11.977 に答える
0

構造的には Iterator に似ていますが、必要な Interface 制約が追加された独自のインターフェイスを作成することをお勧めします。

ここに実際にあるのはオブジェクトのストリームのようです。私はそのルートに行きますが、EOFException などが発生することがあるという付随的な期待があります。

于 2012-10-16T19:15:00.450 に答える
-1

ideoneにサンプルコードを投稿しました。IOIteratorException基本的な考え方は、原因としてIOExceptionのみを除外するカスタムRuntimeExceptionクラスを作成することです。次に、このようなコードを書くことができます

try
{
      iterator . next ( ) ;
}
catch ( IOIteratorException cause )
{
      cause . getCause ( ) ; // the compiler knows this is an IOException so you don't need to cast it
}
于 2012-10-15T11:56:34.760 に答える
-1

チェックされた例外は単なる構文制限です

以下のロンボクのコードhttp://www.projectlombok.org/

あなたが得る

スレッド「メイン」での例外 java.io.IOException at B.main(B.java:19)

public static RuntimeException sneakyThrow(Throwable t) {
    if (t == null) throw new NullPointerException("t");
    B.<RuntimeException>sneakyThrow0(t);
    return null;
}

@SuppressWarnings("unchecked")
private static <T extends Throwable> void sneakyThrow0(Throwable t) throws T {
    throw (T)t;
}

public static void main(String[] args) {
    throw sneakyThrow(new IOException());
}
于 2012-10-09T14:33:22.300 に答える