What methods should go into a java.util.Objects class in JDK 7? (original) (raw)

David Holmes - Sun Microsystems David.Holmes at Sun.COM
Wed Oct 7 03:14:18 UTC 2009


Joe,

Joe Darcy said the following on 10/07/09 09:43:

David Holmes - Sun Microsystems wrote:

I thought the point that Jason Mehrens was making was that this:

+ public static String toString(Object o) { + String.valueOf(o); hat Jason Mehrens was making was that this: + public static String toString(Object o) { + String.valueOf(o); + } is actually pointless. Why introduce + } is actually pointless. Why introduce such redundancy when people can just use String.valueOf directly ? Because, IMO, String.valueOf is obscure and hard to find and from its name it is not clear it does null-safe toString on the argument. For example, I didn't know about String.valueOf. It is much clearer what Objects.toString is intended to do.

It is no more obscure or hard to find than any method one is unaware of. But if you look at any of a number of introductory Java texts - such as The Java Programming Language for example - you will find that valueOf is given good coverage along with the other members of the String class. Further, as David Lloyd points out, there is a strong convention that Type.valueOf(x) converts x to Type - so the Java programmer should be quite familiar with this concept.

I agree the null behaviour is not evident from the name, but nor is it evident from the name toString either - in both cases you must initially check the specification of the method to know what it does.

This doesn't provide any benefit. I think having the new method be commonly called would be a benefit :-)

No more so than having String.valueOf commonly called.

I don't think having a one-line forwarding method in Objects is that harmful.

It is redundant and adds no value. It creates potential confusion because people will wonder why on earth you have two methods that do the exact same thing. (And it's a PITA for authors because it is yet another additional API they have to mention. ;-) )

Just my opinion of course.

David

PS. It should be "return String.valueOf(o);" of course. Fixed. Thanks, -Joe

David Holmes Joe Darcy said the following on 10/07/09 08:50: Joe Darcy wrote: Joe Darcy wrote: Joe Darcy wrote:

Stephen Colebourne wrote:

Joe Darcy wrote:

What other utility methods would have broad enough use and applicability to go into a common java.util class?

Joe, You've asked for a call for ideas, but not given any indication of process. Are you going to evaluate everything that comes in and pick the best a la Coin? Or allow anyone to send in patches? Those options are not mutually exclusive; patches are welcome subject to the usual terms and conditions. Who decides what is in and what is out? This is a little side project of mine and I wanted to get some feedback before preparing a formal change for review, possibly including patches from others. -Joe I'm getting caught up after the JVM Languages Summit and will post some java.util.Objects code for review in the near future. -Joe Below is a patch implementing the methods I think should go into java.util.Objects as a first cut: * null safe two-argument equals method * null safe hashCode(Object) returning 0 for null * null safe toString(Object), returning "null" for a null argument * null tolerating compare method; tests if both arguments are == and if not calls compare The need for the last of these in Objects isn't quite as clear. Var-arg-ifying some of the existing methods in Arrays, (hashCode(Object[]), deepHashCode(Object[]) and toString(Object[])), is probably worthwhile but can be done separately. I wouldn't oppose a toDebugString(Object) method going into the platform somewhere, but I don't think it necessarily belongs in Objects. Further below is the code for an annotation processor which finds candidate equals methods to be replaced with Objects.equals. It found over half a dozen good candidates in the jdk repository. To run the annotation processor, first compile the class and then run it with javac similar to this: javac -proc:only -processor EqualsFinder -processorpath sources -Joe Updated patch of java.util.Objects with some spec clarifications suggested by Alan Bateman and the use of and reference to String.valueOf(Object) observed by Jason Mehrens. -Joe --- /dev/null 2009-08-12 17:12:33.000000000 -0700 +++ new/src/share/classes/java/util/Objects.java 2009-10-06 15:47:16.000000000 -0700 @@ -0,0 +1,100 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.util; + +/** + * This class consists of {@code static} utility methods for operating + * on objects. + * + * @since 1.7 + */ +public class Objects { + private Objects() { + throw new AssertionError("No java.util.Objects instances for you!"); + } + + /** + * 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)); + } + + /** + * 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; + } + + /** + * 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) { + String.valueOf(o); + } + + /** + * Returns 0 if the arguments are identical and {@code + * c.compare(a, b)} otherwise. + * Consequently, if both arguments are {@code null} 0 + * is returned. + * + *

Note that if one of the argument 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 int compare(T a, T b, Comparator<? super T> c) { + return (a == b) ? 0 : c.compare(a, b); + } +}



More information about the core-libs-dev mailing list