• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.testing;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static java.util.Objects.requireNonNull;
21 
22 import com.google.common.annotations.GwtIncompatible;
23 import com.google.common.annotations.J2ktIncompatible;
24 import com.google.common.base.CharMatcher;
25 import com.google.common.base.Charsets;
26 import com.google.common.base.Defaults;
27 import com.google.common.base.Equivalence;
28 import com.google.common.base.Joiner;
29 import com.google.common.base.Predicate;
30 import com.google.common.base.Predicates;
31 import com.google.common.base.Splitter;
32 import com.google.common.base.Stopwatch;
33 import com.google.common.base.Ticker;
34 import com.google.common.collect.BiMap;
35 import com.google.common.collect.ClassToInstanceMap;
36 import com.google.common.collect.ImmutableBiMap;
37 import com.google.common.collect.ImmutableClassToInstanceMap;
38 import com.google.common.collect.ImmutableCollection;
39 import com.google.common.collect.ImmutableList;
40 import com.google.common.collect.ImmutableListMultimap;
41 import com.google.common.collect.ImmutableMap;
42 import com.google.common.collect.ImmutableMultimap;
43 import com.google.common.collect.ImmutableMultiset;
44 import com.google.common.collect.ImmutableSet;
45 import com.google.common.collect.ImmutableSetMultimap;
46 import com.google.common.collect.ImmutableSortedMap;
47 import com.google.common.collect.ImmutableSortedMultiset;
48 import com.google.common.collect.ImmutableSortedSet;
49 import com.google.common.collect.ImmutableTable;
50 import com.google.common.collect.Iterators;
51 import com.google.common.collect.ListMultimap;
52 import com.google.common.collect.MapDifference;
53 import com.google.common.collect.Maps;
54 import com.google.common.collect.Multimap;
55 import com.google.common.collect.Multimaps;
56 import com.google.common.collect.Multiset;
57 import com.google.common.collect.Ordering;
58 import com.google.common.collect.PeekingIterator;
59 import com.google.common.collect.Range;
60 import com.google.common.collect.RowSortedTable;
61 import com.google.common.collect.SetMultimap;
62 import com.google.common.collect.Sets;
63 import com.google.common.collect.SortedMapDifference;
64 import com.google.common.collect.SortedMultiset;
65 import com.google.common.collect.SortedSetMultimap;
66 import com.google.common.collect.Table;
67 import com.google.common.collect.Tables;
68 import com.google.common.collect.TreeBasedTable;
69 import com.google.common.collect.TreeMultimap;
70 import com.google.common.io.ByteSink;
71 import com.google.common.io.ByteSource;
72 import com.google.common.io.ByteStreams;
73 import com.google.common.io.CharSink;
74 import com.google.common.io.CharSource;
75 import com.google.common.primitives.Primitives;
76 import com.google.common.primitives.UnsignedInteger;
77 import com.google.common.primitives.UnsignedLong;
78 import com.google.errorprone.annotations.Keep;
79 import java.io.ByteArrayInputStream;
80 import java.io.ByteArrayOutputStream;
81 import java.io.File;
82 import java.io.InputStream;
83 import java.io.OutputStream;
84 import java.io.PrintStream;
85 import java.io.PrintWriter;
86 import java.io.Reader;
87 import java.io.Serializable;
88 import java.io.StringReader;
89 import java.io.StringWriter;
90 import java.io.Writer;
91 import java.lang.reflect.AnnotatedElement;
92 import java.lang.reflect.Array;
93 import java.lang.reflect.Constructor;
94 import java.lang.reflect.Field;
95 import java.lang.reflect.GenericDeclaration;
96 import java.lang.reflect.InvocationTargetException;
97 import java.lang.reflect.Modifier;
98 import java.lang.reflect.Type;
99 import java.math.BigDecimal;
100 import java.math.BigInteger;
101 import java.nio.Buffer;
102 import java.nio.ByteBuffer;
103 import java.nio.CharBuffer;
104 import java.nio.DoubleBuffer;
105 import java.nio.FloatBuffer;
106 import java.nio.IntBuffer;
107 import java.nio.LongBuffer;
108 import java.nio.ShortBuffer;
109 import java.nio.charset.Charset;
110 import java.util.ArrayDeque;
111 import java.util.Arrays;
112 import java.util.Collection;
113 import java.util.Comparator;
114 import java.util.Currency;
115 import java.util.Deque;
116 import java.util.Iterator;
117 import java.util.List;
118 import java.util.ListIterator;
119 import java.util.Locale;
120 import java.util.Map;
121 import java.util.NavigableMap;
122 import java.util.NavigableSet;
123 import java.util.Optional;
124 import java.util.OptionalDouble;
125 import java.util.OptionalInt;
126 import java.util.OptionalLong;
127 import java.util.Queue;
128 import java.util.Random;
129 import java.util.Set;
130 import java.util.SortedMap;
131 import java.util.SortedSet;
132 import java.util.UUID;
133 import java.util.concurrent.BlockingDeque;
134 import java.util.concurrent.BlockingQueue;
135 import java.util.concurrent.ConcurrentHashMap;
136 import java.util.concurrent.ConcurrentMap;
137 import java.util.concurrent.ConcurrentNavigableMap;
138 import java.util.concurrent.ConcurrentSkipListMap;
139 import java.util.concurrent.CountDownLatch;
140 import java.util.concurrent.Executor;
141 import java.util.concurrent.LinkedBlockingDeque;
142 import java.util.concurrent.ScheduledThreadPoolExecutor;
143 import java.util.concurrent.ThreadFactory;
144 import java.util.concurrent.ThreadPoolExecutor;
145 import java.util.concurrent.TimeUnit;
146 import java.util.logging.Level;
147 import java.util.logging.Logger;
148 import java.util.regex.MatchResult;
149 import java.util.regex.Matcher;
150 import java.util.regex.Pattern;
151 import java.util.stream.Stream;
152 import org.checkerframework.checker.nullness.qual.Nullable;
153 
154 /**
155  * Supplies an arbitrary "default" instance for a wide range of types, often useful in testing
156  * utilities.
157  *
158  * <p>Covers arrays, enums and common types defined in {@code java.lang}, {@code java.lang.reflect},
159  * {@code java.io}, {@code java.nio}, {@code java.math}, {@code java.util}, {@code
160  * java.util.concurrent}, {@code java.util.regex}, {@code com.google.common.base}, {@code
161  * com.google.common.collect} and {@code com.google.common.primitives}. In addition, if the type
162  * exposes at least one public static final constant of the same type, one of the constants will be
163  * used; or if the class exposes a public parameter-less constructor then it will be "new"d and
164  * returned.
165  *
166  * <p>All default instances returned by {@link #get} are generics-safe. Clients won't get type
167  * errors for using {@code get(Comparator.class)} as a {@code Comparator<Foo>}, for example.
168  * Immutable empty instances are returned for collection types; {@code ""} for string; {@code 0} for
169  * number types; reasonable default instance for other stateless types. For mutable types, a fresh
170  * instance is created each time {@code get()} is called.
171  *
172  * @author Kevin Bourrillion
173  * @author Ben Yu
174  * @since 12.0
175  */
176 @GwtIncompatible
177 @J2ktIncompatible
178 @ElementTypesAreNonnullByDefault
179 public final class ArbitraryInstances {
180 
181   private static final Ordering<Field> BY_FIELD_NAME =
182       new Ordering<Field>() {
183         @Override
184         public int compare(Field left, Field right) {
185           return left.getName().compareTo(right.getName());
186         }
187       };
188 
189   /**
190    * Returns a new {@code MatchResult} that corresponds to a successful match. Apache Harmony (used
191    * in Android) requires a successful match in order to generate a {@code MatchResult}:
192    * http://goo.gl/5VQFmC
193    */
newMatchResult()194   private static MatchResult newMatchResult() {
195     Matcher matcher = Pattern.compile(".").matcher("X");
196     matcher.find();
197     return matcher.toMatchResult();
198   }
199 
200   private static final ClassToInstanceMap<Object> DEFAULTS =
201       ImmutableClassToInstanceMap.builder()
202           // primitives
203           .put(Object.class, "")
204           .put(Number.class, 0)
205           .put(UnsignedInteger.class, UnsignedInteger.ZERO)
206           .put(UnsignedLong.class, UnsignedLong.ZERO)
207           .put(BigInteger.class, BigInteger.ZERO)
208           .put(BigDecimal.class, BigDecimal.ZERO)
209           .put(CharSequence.class, "")
210           .put(String.class, "")
211           .put(Pattern.class, Pattern.compile(""))
212           .put(MatchResult.class, newMatchResult())
213           .put(TimeUnit.class, TimeUnit.SECONDS)
214           .put(Charset.class, Charsets.UTF_8)
215           .put(Currency.class, Currency.getInstance(Locale.US))
216           .put(Locale.class, Locale.US)
217           .put(Optional.class, Optional.empty())
218           .put(OptionalInt.class, OptionalInt.empty())
219           .put(OptionalLong.class, OptionalLong.empty())
220           .put(OptionalDouble.class, OptionalDouble.empty())
221           .put(UUID.class, UUID.randomUUID())
222           // common.base
223           .put(CharMatcher.class, CharMatcher.none())
224           .put(Joiner.class, Joiner.on(','))
225           .put(Splitter.class, Splitter.on(','))
226           .put(com.google.common.base.Optional.class, com.google.common.base.Optional.absent())
227           .put(Predicate.class, Predicates.alwaysTrue())
228           .put(Equivalence.class, Equivalence.equals())
229           .put(Ticker.class, Ticker.systemTicker())
230           .put(Stopwatch.class, Stopwatch.createUnstarted())
231           // io types
232           .put(InputStream.class, new ByteArrayInputStream(new byte[0]))
233           .put(ByteArrayInputStream.class, new ByteArrayInputStream(new byte[0]))
234           .put(Readable.class, new StringReader(""))
235           .put(Reader.class, new StringReader(""))
236           .put(StringReader.class, new StringReader(""))
237           .put(Buffer.class, ByteBuffer.allocate(0))
238           .put(CharBuffer.class, CharBuffer.allocate(0))
239           .put(ByteBuffer.class, ByteBuffer.allocate(0))
240           .put(ShortBuffer.class, ShortBuffer.allocate(0))
241           .put(IntBuffer.class, IntBuffer.allocate(0))
242           .put(LongBuffer.class, LongBuffer.allocate(0))
243           .put(FloatBuffer.class, FloatBuffer.allocate(0))
244           .put(DoubleBuffer.class, DoubleBuffer.allocate(0))
245           .put(File.class, new File(""))
246           .put(ByteSource.class, ByteSource.empty())
247           .put(CharSource.class, CharSource.empty())
248           .put(ByteSink.class, NullByteSink.INSTANCE)
249           .put(CharSink.class, NullByteSink.INSTANCE.asCharSink(Charsets.UTF_8))
250           // All collections are immutable empty. So safe for any type parameter.
251           .put(Iterator.class, ImmutableSet.of().iterator())
252           .put(PeekingIterator.class, Iterators.peekingIterator(ImmutableSet.of().iterator()))
253           .put(ListIterator.class, ImmutableList.of().listIterator())
254           .put(Iterable.class, ImmutableSet.of())
255           .put(Collection.class, ImmutableList.of())
256           .put(ImmutableCollection.class, ImmutableList.of())
257           .put(List.class, ImmutableList.of())
258           .put(ImmutableList.class, ImmutableList.of())
259           .put(Set.class, ImmutableSet.of())
260           .put(ImmutableSet.class, ImmutableSet.of())
261           .put(SortedSet.class, ImmutableSortedSet.of())
262           .put(ImmutableSortedSet.class, ImmutableSortedSet.of())
263           .put(NavigableSet.class, Sets.unmodifiableNavigableSet(Sets.newTreeSet()))
264           .put(Map.class, ImmutableMap.of())
265           .put(ImmutableMap.class, ImmutableMap.of())
266           .put(SortedMap.class, ImmutableSortedMap.of())
267           .put(ImmutableSortedMap.class, ImmutableSortedMap.of())
268           .put(NavigableMap.class, Maps.unmodifiableNavigableMap(Maps.newTreeMap()))
269           .put(Multimap.class, ImmutableMultimap.of())
270           .put(ImmutableMultimap.class, ImmutableMultimap.of())
271           .put(ListMultimap.class, ImmutableListMultimap.of())
272           .put(ImmutableListMultimap.class, ImmutableListMultimap.of())
273           .put(SetMultimap.class, ImmutableSetMultimap.of())
274           .put(ImmutableSetMultimap.class, ImmutableSetMultimap.of())
275           .put(
276               SortedSetMultimap.class,
277               Multimaps.unmodifiableSortedSetMultimap(TreeMultimap.create()))
278           .put(Multiset.class, ImmutableMultiset.of())
279           .put(ImmutableMultiset.class, ImmutableMultiset.of())
280           .put(SortedMultiset.class, ImmutableSortedMultiset.of())
281           .put(ImmutableSortedMultiset.class, ImmutableSortedMultiset.of())
282           .put(BiMap.class, ImmutableBiMap.of())
283           .put(ImmutableBiMap.class, ImmutableBiMap.of())
284           .put(Table.class, ImmutableTable.of())
285           .put(ImmutableTable.class, ImmutableTable.of())
286           .put(RowSortedTable.class, Tables.unmodifiableRowSortedTable(TreeBasedTable.create()))
287           .put(ClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
288           .put(ImmutableClassToInstanceMap.class, ImmutableClassToInstanceMap.builder().build())
289           .put(Comparable.class, ByToString.INSTANCE)
290           .put(Comparator.class, AlwaysEqual.INSTANCE)
291           .put(Ordering.class, AlwaysEqual.INSTANCE)
292           .put(Range.class, Range.all())
293           .put(MapDifference.class, Maps.difference(ImmutableMap.of(), ImmutableMap.of()))
294           .put(
295               SortedMapDifference.class,
296               Maps.difference(ImmutableSortedMap.of(), ImmutableSortedMap.of()))
297           // reflect
298           .put(AnnotatedElement.class, Object.class)
299           .put(GenericDeclaration.class, Object.class)
300           .put(Type.class, Object.class)
301           .build();
302 
303   /**
304    * type → implementation. Inherently mutable interfaces and abstract classes are mapped to their
305    * default implementations and are "new"d upon get().
306    */
307   private static final ConcurrentMap<Class<?>, Class<?>> implementations = Maps.newConcurrentMap();
308 
setImplementation(Class<T> type, Class<? extends T> implementation)309   private static <T> void setImplementation(Class<T> type, Class<? extends T> implementation) {
310     checkArgument(type != implementation, "Don't register %s to itself!", type);
311     checkArgument(
312         !DEFAULTS.containsKey(type), "A default value was already registered for %s", type);
313     checkArgument(
314         implementations.put(type, implementation) == null,
315         "Implementation for %s was already registered",
316         type);
317   }
318 
319   static {
setImplementation(Appendable.class, StringBuilder.class)320     setImplementation(Appendable.class, StringBuilder.class);
setImplementation(BlockingQueue.class, LinkedBlockingDeque.class)321     setImplementation(BlockingQueue.class, LinkedBlockingDeque.class);
setImplementation(BlockingDeque.class, LinkedBlockingDeque.class)322     setImplementation(BlockingDeque.class, LinkedBlockingDeque.class);
setImplementation(ConcurrentMap.class, ConcurrentHashMap.class)323     setImplementation(ConcurrentMap.class, ConcurrentHashMap.class);
setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class)324     setImplementation(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class)325     setImplementation(CountDownLatch.class, Dummies.DummyCountDownLatch.class);
setImplementation(Deque.class, ArrayDeque.class)326     setImplementation(Deque.class, ArrayDeque.class);
setImplementation(OutputStream.class, ByteArrayOutputStream.class)327     setImplementation(OutputStream.class, ByteArrayOutputStream.class);
setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class)328     setImplementation(PrintStream.class, Dummies.InMemoryPrintStream.class);
setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class)329     setImplementation(PrintWriter.class, Dummies.InMemoryPrintWriter.class);
setImplementation(Queue.class, ArrayDeque.class)330     setImplementation(Queue.class, ArrayDeque.class);
setImplementation(Random.class, Dummies.DeterministicRandom.class)331     setImplementation(Random.class, Dummies.DeterministicRandom.class);
setImplementation( ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)332     setImplementation(
333         ScheduledThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class)334     setImplementation(ThreadPoolExecutor.class, Dummies.DummyScheduledThreadPoolExecutor.class);
setImplementation(Writer.class, StringWriter.class)335     setImplementation(Writer.class, StringWriter.class);
setImplementation(Runnable.class, Dummies.DummyRunnable.class)336     setImplementation(Runnable.class, Dummies.DummyRunnable.class);
setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class)337     setImplementation(ThreadFactory.class, Dummies.DummyThreadFactory.class);
setImplementation(Executor.class, Dummies.DummyExecutor.class)338     setImplementation(Executor.class, Dummies.DummyExecutor.class);
339   }
340 
341   @SuppressWarnings("unchecked") // it's a subtype map
getImplementation(Class<T> type)342   private static <T> @Nullable Class<? extends T> getImplementation(Class<T> type) {
343     return (Class<? extends T>) implementations.get(type);
344   }
345 
346   private static final Logger logger = Logger.getLogger(ArbitraryInstances.class.getName());
347 
348   /**
349    * Returns an arbitrary instance for {@code type}, or {@code null} if no arbitrary instance can be
350    * determined.
351    */
get(Class<T> type)352   public static <T> @Nullable T get(Class<T> type) {
353     T defaultValue = DEFAULTS.getInstance(type);
354     if (defaultValue != null) {
355       return defaultValue;
356     }
357     Class<? extends T> implementation = getImplementation(type);
358     if (implementation != null) {
359       return get(implementation);
360     }
361     if (type == Stream.class) {
362       return type.cast(Stream.empty());
363     }
364     if (type.isEnum()) {
365       T[] enumConstants = type.getEnumConstants();
366       return (enumConstants == null || enumConstants.length == 0) ? null : enumConstants[0];
367     }
368     if (type.isArray()) {
369       return createEmptyArray(type);
370     }
371     T jvmDefault = Defaults.defaultValue(Primitives.unwrap(type));
372     if (jvmDefault != null) {
373       return jvmDefault;
374     }
375     if (Modifier.isAbstract(type.getModifiers()) || !Modifier.isPublic(type.getModifiers())) {
376       return arbitraryConstantInstanceOrNull(type);
377     }
378     final Constructor<T> constructor;
379     try {
380       constructor = type.getConstructor();
381     } catch (NoSuchMethodException e) {
382       return arbitraryConstantInstanceOrNull(type);
383     }
384     constructor.setAccessible(true); // accessibility check is too slow
385     try {
386       return constructor.newInstance();
387       /*
388        * Do not merge the 2 catch blocks below. javac would infer a type of
389        * ReflectiveOperationException, which Animal Sniffer would reject. (Old versions of
390        * Android don't *seem* to mind, but there might be edge cases of which we're unaware.)
391        */
392     } catch (InstantiationException impossible) {
393       throw new AssertionError(impossible);
394     } catch (IllegalAccessException impossible) {
395       throw new AssertionError(impossible);
396     } catch (InvocationTargetException e) {
397       logger.log(Level.WARNING, "Exception while invoking default constructor.", e.getCause());
398       return arbitraryConstantInstanceOrNull(type);
399     }
400   }
401 
arbitraryConstantInstanceOrNull(Class<T> type)402   private static <T> @Nullable T arbitraryConstantInstanceOrNull(Class<T> type) {
403     Field[] fields = type.getDeclaredFields();
404     Arrays.sort(fields, BY_FIELD_NAME);
405     for (Field field : fields) {
406       if (Modifier.isPublic(field.getModifiers())
407           && Modifier.isStatic(field.getModifiers())
408           && Modifier.isFinal(field.getModifiers())) {
409         if (field.getGenericType() == field.getType() && type.isAssignableFrom(field.getType())) {
410           field.setAccessible(true);
411           try {
412             T constant = type.cast(field.get(null));
413             if (constant != null) {
414               return constant;
415             }
416           } catch (IllegalAccessException impossible) {
417             throw new AssertionError(impossible);
418           }
419         }
420       }
421     }
422     return null;
423   }
424 
createEmptyArray(Class<T> arrayType)425   private static <T> T createEmptyArray(Class<T> arrayType) {
426     // getComponentType() is non-null because we call createEmptyArray only with an array type.
427     return arrayType.cast(Array.newInstance(requireNonNull(arrayType.getComponentType()), 0));
428   }
429 
430   // Internal implementations of some classes, with public default constructor that get() needs.
431   private static final class Dummies {
432 
433     public static final class InMemoryPrintStream extends PrintStream {
InMemoryPrintStream()434       public InMemoryPrintStream() {
435         super(new ByteArrayOutputStream());
436       }
437     }
438 
439     public static final class InMemoryPrintWriter extends PrintWriter {
InMemoryPrintWriter()440       public InMemoryPrintWriter() {
441         super(new StringWriter());
442       }
443     }
444 
445     public static final class DeterministicRandom extends Random {
446       @Keep
DeterministicRandom()447       public DeterministicRandom() {
448         super(0);
449       }
450     }
451 
452     public static final class DummyScheduledThreadPoolExecutor extends ScheduledThreadPoolExecutor {
DummyScheduledThreadPoolExecutor()453       public DummyScheduledThreadPoolExecutor() {
454         super(1);
455       }
456     }
457 
458     public static final class DummyCountDownLatch extends CountDownLatch {
DummyCountDownLatch()459       public DummyCountDownLatch() {
460         super(0);
461       }
462     }
463 
464     public static final class DummyRunnable implements Runnable, Serializable {
465       @Override
run()466       public void run() {}
467     }
468 
469     public static final class DummyThreadFactory implements ThreadFactory, Serializable {
470       @Override
newThread(Runnable r)471       public Thread newThread(Runnable r) {
472         return new Thread(r);
473       }
474     }
475 
476     public static final class DummyExecutor implements Executor, Serializable {
477       @Override
execute(Runnable command)478       public void execute(Runnable command) {}
479     }
480   }
481 
482   private static final class NullByteSink extends ByteSink implements Serializable {
483     private static final NullByteSink INSTANCE = new NullByteSink();
484 
485     @Override
openStream()486     public OutputStream openStream() {
487       return ByteStreams.nullOutputStream();
488     }
489   }
490 
491   // Compare by toString() to satisfy 2 properties:
492   // 1. compareTo(null) should throw NullPointerException
493   // 2. the order is deterministic and easy to understand, for debugging purpose.
494   @SuppressWarnings("ComparableType")
495   private static final class ByToString implements Comparable<Object>, Serializable {
496     private static final ByToString INSTANCE = new ByToString();
497 
498     @Override
compareTo(Object o)499     public int compareTo(Object o) {
500       return toString().compareTo(o.toString());
501     }
502 
503     @Override
toString()504     public String toString() {
505       return "BY_TO_STRING";
506     }
507 
readResolve()508     private Object readResolve() {
509       return INSTANCE;
510     }
511   }
512 
513   // Always equal is a valid total ordering. And it works for any Object.
514   private static final class AlwaysEqual extends Ordering<@Nullable Object>
515       implements Serializable {
516     private static final AlwaysEqual INSTANCE = new AlwaysEqual();
517 
518     @Override
compare(@ullable Object o1, @Nullable Object o2)519     public int compare(@Nullable Object o1, @Nullable Object o2) {
520       return 0;
521     }
522 
523     @Override
toString()524     public String toString() {
525       return "ALWAYS_EQUAL";
526     }
527 
readResolve()528     private Object readResolve() {
529       return INSTANCE;
530     }
531   }
532 
ArbitraryInstances()533   private ArbitraryInstances() {}
534 }
535