001 /* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package com.google.common.base; 018 019 import static com.google.common.base.Preconditions.checkNotNull; 020 021 import com.google.common.annotations.GwtCompatible; 022 023 import java.util.Arrays; 024 025 import javax.annotation.Nullable; 026 027 /** 028 * Helper functions that can operate on any {@code Object}. 029 * 030 * @author Laurence Gonsalves 031 * @since 2.0 (imported from Google Collections Library) 032 */ 033 @GwtCompatible 034 public final class Objects { 035 private Objects() {} 036 037 /** 038 * Determines whether two possibly-null objects are equal. Returns: 039 * 040 * <ul> 041 * <li>{@code true} if {@code a} and {@code b} are both null. 042 * <li>{@code true} if {@code a} and {@code b} are both non-null and they are 043 * equal according to {@link Object#equals(Object)}. 044 * <li>{@code false} in all other situations. 045 * </ul> 046 * 047 * <p>This assumes that any non-null objects passed to this function conform 048 * to the {@code equals()} contract. 049 */ 050 public static boolean equal(@Nullable Object a, @Nullable Object b) { 051 return a == b || (a != null && a.equals(b)); 052 } 053 054 /** 055 * Generates a hash code for multiple values. The hash code is generated by 056 * calling {@link Arrays#hashCode(Object[])}. 057 * 058 * <p>This is useful for implementing {@link Object#hashCode()}. For example, 059 * in an object that has three properties, {@code x}, {@code y}, and 060 * {@code z}, one could write: 061 * <pre> 062 * public int hashCode() { 063 * return Objects.hashCode(getX(), getY(), getZ()); 064 * }</pre> 065 * 066 * <b>Warning</b>: When a single object is supplied, the returned hash code 067 * does not equal the hash code of that object. 068 */ 069 public static int hashCode(@Nullable Object... objects) { 070 return Arrays.hashCode(objects); 071 } 072 073 /** 074 * Creates an instance of {@link ToStringHelper}. 075 * 076 * <p>This is helpful for implementing {@link Object#toString()}. 077 * Specification by example: <pre> {@code 078 * // Returns "ClassName{}" 079 * Objects.toStringHelper(this) 080 * .toString(); 081 * 082 * // Returns "ClassName{x=1}" 083 * Objects.toStringHelper(this) 084 * .add("x", 1) 085 * .toString(); 086 * 087 * // Returns "MyObject{x=1}" 088 * Objects.toStringHelper("MyObject") 089 * .add("x", 1) 090 * .toString(); 091 * 092 * // Returns "ClassName{x=1, y=foo}" 093 * Objects.toStringHelper(this) 094 * .add("x", 1) 095 * .add("y", "foo") 096 * .toString(); 097 * }}</pre> 098 * 099 * <p>Note that in GWT, class names are often obfuscated. 100 * 101 * @param self the object to generate the string for (typically {@code this}), 102 * used only for its class name 103 * @since 2.0 104 */ 105 public static ToStringHelper toStringHelper(Object self) { 106 return new ToStringHelper(simpleName(self.getClass())); 107 } 108 109 /** 110 * Creates an instance of {@link ToStringHelper} in the same manner as 111 * {@link Objects#toStringHelper(Object)}, but using the name of {@code clazz} 112 * instead of using an instance's {@link Object#getClass()}. 113 * 114 * <p>Note that in GWT, class names are often obfuscated. 115 * 116 * @param clazz the {@link Class} of the instance 117 * @since 7.0 (source-compatible since 2.0) 118 */ 119 public static ToStringHelper toStringHelper(Class<?> clazz) { 120 return new ToStringHelper(simpleName(clazz)); 121 } 122 123 /** 124 * Creates an instance of {@link ToStringHelper} in the same manner as 125 * {@link Objects#toStringHelper(Object)}, but using {@code className} instead 126 * of using an instance's {@link Object#getClass()}. 127 * 128 * @param className the name of the instance type 129 * @since 7.0 (source-compatible since 2.0) 130 */ 131 public static ToStringHelper toStringHelper(String className) { 132 return new ToStringHelper(className); 133 } 134 135 /** 136 * {@link Class#getSimpleName()} is not GWT compatible yet, so we 137 * provide our own implementation. 138 */ 139 private static String simpleName(Class<?> clazz) { 140 String name = clazz.getName(); 141 142 // the nth anonymous class has a class name ending in "Outer$n" 143 // and local inner classes have names ending in "Outer.$1Inner" 144 name = name.replaceAll("\\$[0-9]+", "\\$"); 145 146 // we want the name of the inner class all by its lonesome 147 int start = name.lastIndexOf('$'); 148 149 // if this isn't an inner class, just find the start of the 150 // top level class name. 151 if (start == -1) { 152 start = name.lastIndexOf('.'); 153 } 154 return name.substring(start + 1); 155 } 156 157 /** 158 * Returns the first of two given parameters that is not {@code null}, if 159 * either is, or otherwise throws a {@link NullPointerException}. 160 * 161 * <p><b>Note:</b> if {@code first} is represented as an {@code Optional<T>}, 162 * this can be accomplished with {@code first.or(second)}. That approach also 163 * allows for lazy evaluation of the fallback instance, using 164 * {@code first.or(Supplier)}. 165 * 166 * @return {@code first} if {@code first} is not {@code null}, or 167 * {@code second} if {@code first} is {@code null} and {@code second} is 168 * not {@code null} 169 * @throws NullPointerException if both {@code first} and {@code second} were 170 * {@code null} 171 * @since 3.0 172 */ 173 public static <T> T firstNonNull(@Nullable T first, @Nullable T second) { 174 return first != null ? first : checkNotNull(second); 175 } 176 177 /** 178 * Support class for {@link Objects#toStringHelper}. 179 * 180 * @author Jason Lee 181 * @since 2.0 182 */ 183 public static final class ToStringHelper { 184 private final StringBuilder builder; 185 private boolean needsSeparator = false; 186 187 /** 188 * Use {@link Objects#toStringHelper(Object)} to create an instance. 189 */ 190 private ToStringHelper(String className) { 191 checkNotNull(className); 192 this.builder = new StringBuilder(32).append(className).append('{'); 193 } 194 195 /** 196 * Adds a name/value pair to the formatted output in {@code name=value} 197 * format. If {@code value} is {@code null}, the string {@code "null"} 198 * is used. 199 */ 200 public ToStringHelper add(String name, @Nullable Object value) { 201 checkNotNull(name); 202 maybeAppendSeparator().append(name).append('=').append(value); 203 return this; 204 } 205 206 /** 207 * Adds a value to the formatted output in {@code value} format. 208 * 209 * <p>It is strongly encouraged to use {@link #add(String, Object)} instead 210 * and give value a readable name. 211 */ 212 public ToStringHelper addValue(@Nullable Object value) { 213 maybeAppendSeparator().append(value); 214 return this; 215 } 216 217 /** 218 * Returns a string in the format specified by {@link 219 * Objects#toStringHelper(Object)}. 220 */ 221 @Override public String toString() { 222 try { 223 return builder.append('}').toString(); 224 } finally { 225 // Slice off the closing brace in case there are additional calls to 226 // #add or #addValue. 227 builder.setLength(builder.length() - 1); 228 } 229 } 230 231 private StringBuilder maybeAppendSeparator() { 232 if (needsSeparator) { 233 return builder.append(", "); 234 } else { 235 needsSeparator = true; 236 return builder; 237 } 238 } 239 } 240 }