First round of java.util.Objects for code review (bug 6797535)
Joshua Bloch
jjb at google.com
Thu Oct 8 21:56:13 UTC 2009
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.
+
> + /**
> + * 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.
> +
> + /**
> + * 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.
> +
> + /**
> + * 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.
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.
Regards,
Josh Bloch and Bob Lee
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/core-libs-dev/attachments/20091008/4b1809d0/attachment.html>
More information about the core-libs-dev
mailing list