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 no...@code null} argument and 0 for
    +     * a {...@code null} argument.
    +     *
    +     * @return the hash code of a no...@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>
     * &#064;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
    no...@code
    +     * null} argument and {...@code "null"} for a {...@code null} argument.
    +     *
    +     * @return the result of calling {...@code toString} for a
    no...@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

Reply via email to