RFR 8015008: Primitive iterator over empty sequence, null consumer: forEachRemaining methods do not throw NPE
Chris Hegarty
chris.hegarty at oracle.com
Wed May 29 14:37:57 UTC 2013
Looks fine to me Paul.
On 29/05/2013 12:35, Paul Sandoz wrote:
> Hi,
>
> Please review these changes to j.u.PrimitiveIterator to ensure the default forEachRemaining methods consistently throw an NPE when the consumer is null.
>
> I almost produced a webrev for this, but i thought it was just about acceptable size-wise and i hope easy to review in textual form. If this is considered impolite, awkward to review etc please say so and i will produce a webrev.
I found it a little difficult to review as it lacked some context around
the changes. I found myself having to track down the source and compare
line numbers. Not a problem, just that you happen to mention it ;-)
-Chris
>
> Paul.
>
> # HG changeset patch
> # User psandoz
> # Date 1369825083 -7200
> # Node ID 7ded996200218791c885c0aae4c474066101c7bd
> # Parent bfdc1ed75460c9e6869827cf9acabd4b1a5e9d29
> 8015008: Primitive iterator over empty sequence, null consumer: forEachRemaining methods do not throw NPE
> Reviewed-by:
>
> diff -r bfdc1ed75460 -r 7ded99620021 src/share/classes/java/util/PrimitiveIterator.java
> --- a/src/share/classes/java/util/PrimitiveIterator.java Wed May 29 12:58:02 2013 +0200
> +++ b/src/share/classes/java/util/PrimitiveIterator.java Wed May 29 12:58:03 2013 +0200
> @@ -91,6 +91,7 @@
> * @throws NullPointerException if the specified action is null
> */
> default void forEachRemaining(IntConsumer action) {
> + Objects.requireNonNull(action);
> while (hasNext())
> action.accept(nextInt());
> }
> @@ -123,6 +124,8 @@
> forEachRemaining((IntConsumer) action);
> }
> else {
> + // The method reference action::accept is never null
> + Objects.requireNonNull(action);
> if (Tripwire.ENABLED)
> Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfInt.forEachRemainingInt(action::accept)");
> forEachRemaining((IntConsumer) action::accept);
> @@ -162,6 +165,7 @@
> * @throws NullPointerException if the specified action is null
> */
> default void forEachRemaining(LongConsumer action) {
> + Objects.requireNonNull(action);
> while (hasNext())
> action.accept(nextLong());
> }
> @@ -194,6 +198,8 @@
> forEachRemaining((LongConsumer) action);
> }
> else {
> + // The method reference action::accept is never null
> + Objects.requireNonNull(action);
> if (Tripwire.ENABLED)
> Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfLong.forEachRemainingLong(action::accept)");
> forEachRemaining((LongConsumer) action::accept);
> @@ -232,6 +238,7 @@
> * @throws NullPointerException if the specified action is null
> */
> default void forEachRemaining(DoubleConsumer action) {
> + Objects.requireNonNull(action);
> while (hasNext())
> action.accept(nextDouble());
> }
> @@ -265,6 +272,8 @@
> forEachRemaining((DoubleConsumer) action);
> }
> else {
> + // The method reference action::accept is never null
> + Objects.requireNonNull(action);
> if (Tripwire.ENABLED)
> Tripwire.trip(getClass(), "{0} calling PrimitiveIterator.OfDouble.forEachRemainingDouble(action::accept)");
> forEachRemaining((DoubleConsumer) action::accept);
> diff -r bfdc1ed75460 -r 7ded99620021 test/java/util/Iterator/PrimitiveIteratorDefaults.java
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/test/java/util/Iterator/PrimitiveIteratorDefaults.java Wed May 29 12:58:03 2013 +0200
> @@ -0,0 +1,115 @@
> +/*
> + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
> + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
> + *
> + * This code is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 only, as
> + * published by the Free Software Foundation.
> + *
> + * This code is distributed in the hope that it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
> + * version 2 for more details (a copy is included in the LICENSE file that
> + * accompanied this code).
> + *
> + * You should have received a copy of the GNU General Public License version
> + * 2 along with this work; if not, write to the Free Software Foundation,
> + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
> + *
> + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
> + * or visit www.oracle.com if you need additional information or have any
> + * questions.
> + */
> +
> +import org.testng.annotations.Test;
> +
> +import java.util.PrimitiveIterator;
> +import java.util.function.Consumer;
> +import java.util.function.DoubleConsumer;
> +import java.util.function.IntConsumer;
> +import java.util.function.LongConsumer;
> +
> +import static org.testng.Assert.assertNotNull;
> +import static org.testng.Assert.assertTrue;
> +
> +/**
> + * @test
> + * @run testng PrimitiveIteratorDefaults
> + * @summary test default methods on PrimitiveIterator
> + */
> + at Test
> +public class PrimitiveIteratorDefaults {
> +
> + public void testIntForEachRemainingWithNull() {
> + PrimitiveIterator.OfInt i = new PrimitiveIterator.OfInt() {
> + @Override
> + public int nextInt() {
> + return 0;
> + }
> +
> + @Override
> + public boolean hasNext() {
> + return false;
> + }
> + };
> +
> + executeAndCatch(() -> i.forEachRemaining((IntConsumer) null));
> + executeAndCatch(() -> i.forEachRemaining((Consumer<Integer>) null));
> + }
> +
> + public void testLongForEachRemainingWithNull() {
> + PrimitiveIterator.OfLong i = new PrimitiveIterator.OfLong() {
> + @Override
> + public long nextLong() {
> + return 0;
> + }
> +
> + @Override
> + public boolean hasNext() {
> + return false;
> + }
> + };
> +
> + executeAndCatch(() -> i.forEachRemaining((LongConsumer) null));
> + executeAndCatch(() -> i.forEachRemaining((Consumer<Long>) null));
> + }
> +
> + public void testDoubleForEachRemainingWithNull() {
> + PrimitiveIterator.OfDouble i = new PrimitiveIterator.OfDouble() {
> + @Override
> + public double nextDouble() {
> + return 0;
> + }
> +
> + @Override
> + public boolean hasNext() {
> + return false;
> + }
> + };
> +
> + executeAndCatch(() -> i.forEachRemaining((DoubleConsumer) null));
> + executeAndCatch(() -> i.forEachRemaining((Consumer<Double>) null));
> + }
> +
> + private void executeAndCatch(Runnable r) {
> + executeAndCatch(NullPointerException.class, r);
> + }
> +
> + private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
> + Exception caught = null;
> + try {
> + r.run();
> + }
> + catch (Exception e) {
> + caught = e;
> + }
> +
> + assertNotNull(caught,
> + String.format("No Exception was thrown, expected an Exception of %s to be thrown",
> + expected.getName()));
> + assertTrue(expected.isInstance(caught),
> + String.format("Exception thrown %s not an instance of %s",
> + caught.getClass().getName(), expected.getName()));
> + }
> +
> +}
>
More information about the core-libs-dev
mailing list