AbstractIterator extends UnmodifiableIterator<T> { @Override public final boolean hasNext() { if (state == State.FAILED){ throw new IllegalStateException("Iterator in " + State.FAILED + " state"); } switch (state) { case DONE: return false; case READY: return true; default: } return tryToComputeNext(); } protected  AbstractIterator(); @Override final boolean hasNext(); @Override final T next(); final T peek();  }
@Test public void testException() { final SomeUncheckedException exception = new SomeUncheckedException(); Iterator<Integer> iter = new AbstractIterator<Integer>() { @Override public Integer computeNext() { throw exception; } }; try { iter.hasNext(); fail("No exception thrown"); } catch (SomeUncheckedException e) { assertSame(exception, e); } }
@Test public void testReentrantHasNext() { Iterator<Integer> iter = new AbstractIterator<Integer>() { @Override protected Integer computeNext() { hasNext(); return null; } }; try { iter.hasNext(); fail(); } catch (IllegalStateException expected) { } }
@Test public void testSneakyThrow() throws Exception { Iterator<Integer> iter = new AbstractIterator<Integer>() { boolean haveBeenCalled; @Override public Integer computeNext() { if (haveBeenCalled) { fail("Should not have been called again"); } else { haveBeenCalled = true; sneakyThrow(new SomeCheckedException()); } return null; } }; try { iter.hasNext(); fail("No exception thrown"); } catch (Exception e) { if (!(e instanceof SomeCheckedException)) { throw e; } } try { iter.hasNext(); fail("No exception thrown"); } catch (IllegalStateException expected) { } }