First round of java.util.Objects for code review (bug 6797535)
Joe Darcy
Joe.Darcy at Sun.COM
Fri Oct 9 01:21:52 UTC 2009
Hello.
Joshua Bloch wrote:
> Joe,
>
> Hi. I think it's great that you're doing this. A few comments:
>
>
> +public class Objects {
> + private Objects() {
> + throw new AssertionError("No java.util.Objects instances
> for you!");
> + }
>
> Cute!
>
>
> +
> + /**
> + * Returns {@code true} if the arguments are equal to each other
> + * and {@code false} otherwise.
> + * Consequently, if both arguments are {@code null}, {@code true}
> + * is returned and if exactly one argument is {@code null},
> {@code
> + * false} is returned. Otherwise, equality is determined by
> using
> + * the {@link Object#equals equals} method of the first
> + * argument.
> + *
> + * @return {@code true} if the arguments are equal to each other
> + * and {@code false} otherwise
> + * @see Object#equals(Object)
> + */
> + public static boolean equals(Object a, Object b) {
> + return (a == b) || (a != null && a.equals(b));
> + }
>
> Very useful! We've needed this one ( equals(Object a, Object b) )
> for years.
Indeed.
>
> +
> + /**
> + * Returns the hash code of a non-{@code null} argument and 0 for
> + * a {@code null} argument.
> + *
> + * @return the hash code of a non-{@code null} argument and 0 for
> + * a {@code null} argument
> + * @see Object#hashCode
> + */
> + public static int hashCode(Object o) {
> + return o != null ? o.hashCode() : 0;
> + }
>
>
> Again, very useful. Along these lines, I would add this method too:
>
> /**
> * Generates a hash code for a sequence of input values. The hash
> code is
> * generated as if all the input values were placed into an array,
> and that
> * array were hashed by calling {@link Arrays#hashCode(Object[])}.
> * <p/>
> * <p>This method is useful for implementing {@link
> Object#hashCode()} on
> * objects containing multiple fields. For example, if an object
> that has
> * three fields, {@code x}, {@code y}, and {@code z}, one could
> write:
> * <pre>
> * @Override public int hashCode() {
> * return Objects.hashCode(x, y, z);
> * }
> * </pre>
> * <b>Warning: When a single object reference is supplied, the
> returned
> * value does not equal the hash code of that object
> reference.</b> This
> * value can be computed by calling {@link #hashCode(Object)}.
> */
> public static int hash(Object... components) {
> return Arrays.hashCode(components);
> }
>
> People still don't know how to hash objects with multiple fields; this
> little method makes it much easier.
Hmm. I split up a number of the follow-up ideas into separate email
threads on core-libs-deve; one of those was whether or not some of the
existing methods in Arrays should be var-argified.
What about introducing a java.util.Hash (Hasher?) class with
* hash methods for double and long implementing the Long and Double hash
code algorithms, etc.
* the hash convenience method above
>
>
> +
> + /**
> + * Returns the result of calling {@code toString} for a
> non-{@code
> + * null} argument and {@code "null"} for a {@code null} argument.
> + *
> + * @return the result of calling {@code toString} for a
> non-{@code
> + * null} argument and {@code "null"} for a {@code null} argument
> + * @see Object#toString
> + * @see String#valueOf(Object)
> + */
> + public static String toString(Object o) {
> + return String.valueOf(o);
> + }
>
> I would definitely /not/ add this method (Objects.toString). It
> brings nothing to the table that isn't already there. People know and
> use String.valueOf. Let's not muddy the waters by adding another choice.
So noted.
>
>
> +
> + /**
> + * Returns 0 if the arguments are identical and {@code
> + * c.compare(a, b)} otherwise.
> + * Consequently, if both arguments are {@code null} 0
> + * is returned.
> + *
> + * <p>Note that if one of the arguments is {@code null}, a {@code
> + * NullPointerException} may or may not be thrown depending on
> + * what ordering policy, if any, the {@link Comparator
> Comparator}
> + * chooses to have for {@code null} values.
> + *
> + * @return 0 if the arguments are identical and {@code
> + * c.compare(a, b)} otherwise.
> + * @see Comparable
> + * @see Comparator
> + */
> + public static <T> int compare(T a, T b, Comparator<? super T>
> c) {
> + return (a == b) ? 0 : c.compare(a, b);
> + }
> +}
>
> I don't think you should add this method ( compare(T a, T b,
> Comparator<? super T> c)). Its utility is unclear, and it doesn't
> have the power-to-weight ratio of the other methods in this class.
Yeah, I included this with "Item 12: Consider implementing Comparable"
from EJv2 in mind.
>
> I strongly suggest that you do add these two methods:
>
> /**
> * Checks that the specified object reference is not {@code null}.
> This
> * method is designed primarily for doing parameter validation in
> methods
> * and constructors, as demonstrated below:
> * <pre>
> * public Foo(Bar bar) {
> * this.bar = Objects.nonNull(bar);
> * }
> * </pre>
> *
> * @param obj the object reference to check for nullity
> * @return {@code obj} if not {@code null}
> * @throws NullPointerException if {@code obj} is {@code null}
> */
> public static <T> T nonNull(T obj) {
> if (obj == null)
> throw new NullPointerException();
> return obj;
> }
>
> /**
> * Checks that the specified object reference is not {@code null} and
> * throws a customized {@Link NullPointerException} if it is. This
> method
> * is designed primarily for doing parameter validation in methods and
> * constructors with multiple parameters, as demonstrated below:
> * <pre>
> * public Foo(Bar bar, Baz baz) {
> * this.bar = Objects.nonNull(bar, "bar must not be null");
> * this.baz = Objects.nonNull(baz, "baz must not be null");
> * }
> * </pre>
> *
> * @param obj the object reference to check for nullity
> * @param message detail message to be used in the event that a {@code
> * NullPointerException} is thrown
> * @return {@code obj} if not {@code null}
> * @throws NullPointerException if {@code obj} is {@code null}
> */
> public static <T> T nonNull(T obj, String message) {
> if (obj == null)
> throw new NullPointerException(message);
> return obj;
> }
>
> They do a great job reducing the verbiage in validity-checking of
> arguments that must not be null.
I've filed bug 6889858 "Add nonNull methods to java.util.Objects" for
these last two methods. If you want to finish off the engineering need
for a changeset, some light tests, etc., I'll file the Sun-internal
paperwork for these.
Once the Mercurial repos are feeling healthy again, I'm going to push
the four-method version of j.u.Objects (equals(Object, Object),
hashCode(Object), toString(Object), compare(T, T)) into JDK 7 TL.
Afterward I expect discussions of refinements, changes, and additions to
j.u.Objects to continue on the mailing list.
-Joe
More information about the core-libs-dev
mailing list