1 /*
2  * Copyright (C) 2010 Google Inc.
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.inject;
18 
19 import static com.google.inject.Asserts.*;
20 import static com.google.inject.name.Names.named;
21 
22 import com.google.common.base.Objects;
23 import com.google.common.collect.Lists;
24 import com.google.inject.name.Named;
25 import com.google.inject.spi.Element;
26 import com.google.inject.spi.Elements;
27 import com.google.inject.util.Providers;
28 import java.lang.annotation.Annotation;
29 import java.lang.reflect.Constructor;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.LinkedHashSet;
33 import java.util.List;
34 import java.util.logging.Logger;
35 import junit.framework.TestCase;
36 
37 /**
38  * A suite of tests for duplicate bindings.
39  *
40  * @author sameb@google.com (Sam Berlin)
41  */
42 public class DuplicateBindingsTest extends TestCase {
43 
44   private FooImpl foo = new FooImpl();
45   private Provider<Foo> pFoo = Providers.<Foo>of(new FooImpl());
46   private Class<? extends Provider<? extends Foo>> pclFoo = FooProvider.class;
47   private Class<? extends Foo> clFoo = FooImpl.class;
48   private Constructor<FooImpl> cFoo = FooImpl.cxtor();
49 
testDuplicateBindingsAreIgnored()50   public void testDuplicateBindingsAreIgnored() {
51     Injector injector =
52         Guice.createInjector(
53             new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
54             new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
55     List<Key<?>> bindings = Lists.newArrayList(injector.getAllBindings().keySet());
56     removeBasicBindings(bindings);
57 
58     // Ensure only one binding existed for each type.
59     assertTrue(bindings.remove(Key.get(Foo.class, named("instance"))));
60     assertTrue(bindings.remove(Key.get(Foo.class, named("pInstance"))));
61     assertTrue(bindings.remove(Key.get(Foo.class, named("pKey"))));
62     assertTrue(bindings.remove(Key.get(Foo.class, named("linkedKey"))));
63     assertTrue(bindings.remove(Key.get(FooImpl.class)));
64     assertTrue(bindings.remove(Key.get(Foo.class, named("constructor"))));
65     assertTrue(bindings.remove(Key.get(FooProvider.class))); // JIT binding
66     assertTrue(bindings.remove(Key.get(Foo.class, named("providerMethod"))));
67 
68     assertEquals(bindings.toString(), 0, bindings.size());
69   }
70 
testElementsDeduplicate()71   public void testElementsDeduplicate() {
72     List<Element> elements =
73         Elements.getElements(
74             new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
75             new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
76     assertEquals(14, elements.size());
77     assertEquals(7, new LinkedHashSet<Element>(elements).size());
78   }
79 
testProviderMethodsFailIfInstancesDiffer()80   public void testProviderMethodsFailIfInstancesDiffer() {
81     try {
82       Guice.createInjector(new FailingProviderModule(), new FailingProviderModule());
83       fail("should have failed");
84     } catch (CreationException ce) {
85       assertContains(
86           ce.getMessage(),
87           "A binding to "
88               + Foo.class.getName()
89               + " was already configured "
90               + "at "
91               + FailingProviderModule.class.getName(),
92           "at " + FailingProviderModule.class.getName());
93     }
94   }
95 
testSameScopeInstanceIgnored()96   public void testSameScopeInstanceIgnored() {
97     Guice.createInjector(
98         new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo),
99         new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo));
100 
101     Guice.createInjector(
102         new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo),
103         new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo));
104   }
105 
testSameScopeAnnotationIgnored()106   public void testSameScopeAnnotationIgnored() {
107     Guice.createInjector(
108         new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo),
109         new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo));
110   }
111 
testMixedAnnotationAndScopeForSingletonIgnored()112   public void testMixedAnnotationAndScopeForSingletonIgnored() {
113     Guice.createInjector(
114         new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo),
115         new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo));
116   }
117 
testMixedScopeAndUnscopedIgnored()118   public void testMixedScopeAndUnscopedIgnored() {
119     Guice.createInjector(
120         new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
121         new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo));
122   }
123 
testMixedScopeFails()124   public void testMixedScopeFails() {
125     try {
126       Guice.createInjector(
127           new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
128           new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo));
129       fail("expected exception");
130     } catch (CreationException ce) {
131       String segment1 =
132           "A binding to "
133               + Foo.class.getName()
134               + " annotated with "
135               + named("pInstance")
136               + " was already configured at "
137               + SimpleModule.class.getName();
138       String segment2 =
139           "A binding to "
140               + Foo.class.getName()
141               + " annotated with "
142               + named("pKey")
143               + " was already configured at "
144               + SimpleModule.class.getName();
145       String segment3 =
146           "A binding to "
147               + Foo.class.getName()
148               + " annotated with "
149               + named("constructor")
150               + " was already configured at "
151               + SimpleModule.class.getName();
152       String segment4 =
153           "A binding to "
154               + FooImpl.class.getName()
155               + " was already configured at "
156               + SimpleModule.class.getName();
157       String atSegment = "at " + ScopedModule.class.getName();
158       if (isIncludeStackTraceOff()) {
159         assertContains(
160             ce.getMessage(),
161             segment1,
162             atSegment,
163             segment2,
164             atSegment,
165             segment3,
166             atSegment,
167             segment4,
168             atSegment);
169       } else {
170         assertContains(
171             ce.getMessage(),
172             segment1,
173             atSegment,
174             segment2,
175             atSegment,
176             segment4,
177             atSegment,
178             segment3,
179             atSegment);
180       }
181     }
182   }
183 
184   @SuppressWarnings("unchecked")
testMixedTargetsFails()185   public void testMixedTargetsFails() {
186     try {
187       Guice.createInjector(
188           new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
189           new SimpleModule(
190               new FooImpl(),
191               Providers.<Foo>of(new FooImpl()),
192               (Class) BarProvider.class,
193               (Class) Bar.class,
194               (Constructor) Bar.cxtor()));
195       fail("expected exception");
196     } catch (CreationException ce) {
197       assertContains(
198           ce.getMessage(),
199           "A binding to "
200               + Foo.class.getName()
201               + " annotated with "
202               + named("pInstance")
203               + " was already configured at "
204               + SimpleModule.class.getName(),
205           "at " + SimpleModule.class.getName(),
206           "A binding to "
207               + Foo.class.getName()
208               + " annotated with "
209               + named("pKey")
210               + " was already configured at "
211               + SimpleModule.class.getName(),
212           "at " + SimpleModule.class.getName(),
213           "A binding to "
214               + Foo.class.getName()
215               + " annotated with "
216               + named("linkedKey")
217               + " was already configured at "
218               + SimpleModule.class.getName(),
219           "at " + SimpleModule.class.getName(),
220           "A binding to "
221               + Foo.class.getName()
222               + " annotated with "
223               + named("constructor")
224               + " was already configured at "
225               + SimpleModule.class.getName(),
226           "at " + SimpleModule.class.getName());
227     }
228   }
229 
testExceptionInEqualsThrowsCreationException()230   public void testExceptionInEqualsThrowsCreationException() {
231     try {
232       Guice.createInjector(new ThrowingModule(), new ThrowingModule());
233       fail("expected exception");
234     } catch (CreationException ce) {
235       assertContains(
236           ce.getMessage(),
237           "A binding to "
238               + Foo.class.getName()
239               + " was already configured at "
240               + ThrowingModule.class.getName(),
241           "and an error was thrown while checking duplicate bindings.  Error: java.lang.RuntimeException: Boo!",
242           "at " + ThrowingModule.class.getName());
243     }
244   }
245 
testChildInjectorDuplicateParentFail()246   public void testChildInjectorDuplicateParentFail() {
247     Injector injector = Guice.createInjector(new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
248 
249     try {
250       injector.createChildInjector(new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
251       fail("expected exception");
252     } catch (CreationException ce) {
253       assertContains(
254           ce.getMessage(),
255           "A binding to "
256               + Foo.class.getName()
257               + " annotated with "
258               + named("pInstance")
259               + " was already configured at "
260               + SimpleModule.class.getName(),
261           "at " + SimpleModule.class.getName(),
262           "A binding to "
263               + Foo.class.getName()
264               + " annotated with "
265               + named("pKey")
266               + " was already configured at "
267               + SimpleModule.class.getName(),
268           "at " + SimpleModule.class.getName(),
269           "A binding to "
270               + Foo.class.getName()
271               + " annotated with "
272               + named("linkedKey")
273               + " was already configured at "
274               + SimpleModule.class.getName(),
275           "at " + SimpleModule.class.getName(),
276           "A binding to "
277               + Foo.class.getName()
278               + " annotated with "
279               + named("constructor")
280               + " was already configured at "
281               + SimpleModule.class.getName(),
282           "at " + SimpleModule.class.getName(),
283           "A binding to "
284               + Foo.class.getName()
285               + " annotated with "
286               + named("providerMethod")
287               + " was already configured at "
288               + SimpleProviderModule.class.getName(),
289           "at " + SimpleProviderModule.class.getName());
290     }
291   }
292 
testDuplicatesSolelyInChildIgnored()293   public void testDuplicatesSolelyInChildIgnored() {
294     Injector injector = Guice.createInjector();
295     injector.createChildInjector(
296         new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
297         new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo));
298   }
299 
testDifferentBindingTypesFail()300   public void testDifferentBindingTypesFail() {
301     List<Element> elements = Elements.getElements(new FailedModule(foo, pFoo, pclFoo, clFoo, cFoo));
302 
303     // Make sure every combination of the elements with another element fails.
304     // This ensures that duplication checks the kind of binding also.
305     for (Element e1 : elements) {
306       for (Element e2 : elements) {
307         // if they're the same, this shouldn't fail.
308         try {
309           Guice.createInjector(Elements.getModule(Arrays.asList(e1, e2)));
310           if (e1 != e2) {
311             fail("must fail!");
312           }
313         } catch (CreationException expected) {
314           if (e1 != e2) {
315             assertContains(
316                 expected.getMessage(),
317                 "A binding to "
318                     + Foo.class.getName()
319                     + " was already configured at "
320                     + FailedModule.class.getName(),
321                 "at " + FailedModule.class.getName());
322           } else {
323             throw expected;
324           }
325         }
326       }
327     }
328   }
329 
testJitBindingsAreCheckedAfterConversions()330   public void testJitBindingsAreCheckedAfterConversions() {
331     Guice.createInjector(
332         new AbstractModule() {
333           @Override
334           protected void configure() {
335             bind(A.class);
336             bind(A.class).to(RealA.class);
337           }
338         });
339   }
340 
testEqualsNotCalledByDefaultOnInstance()341   public void testEqualsNotCalledByDefaultOnInstance() {
342     final HashEqualsTester a = new HashEqualsTester();
343     a.throwOnEquals = true;
344     Guice.createInjector(
345         new AbstractModule() {
346           @Override
347           protected void configure() {
348             bind(String.class);
349             bind(HashEqualsTester.class).toInstance(a);
350           }
351         });
352   }
353 
testEqualsNotCalledByDefaultOnProvider()354   public void testEqualsNotCalledByDefaultOnProvider() {
355     final HashEqualsTester a = new HashEqualsTester();
356     a.throwOnEquals = true;
357     Guice.createInjector(
358         new AbstractModule() {
359           @Override
360           protected void configure() {
361             bind(String.class);
362             bind(Object.class).toProvider(a);
363           }
364         });
365   }
366 
testHashcodeNeverCalledOnInstance()367   public void testHashcodeNeverCalledOnInstance() {
368     final HashEqualsTester a = new HashEqualsTester();
369     a.throwOnHashcode = true;
370     a.equality = "test";
371 
372     final HashEqualsTester b = new HashEqualsTester();
373     b.throwOnHashcode = true;
374     b.equality = "test";
375     Guice.createInjector(
376         new AbstractModule() {
377           @Override
378           protected void configure() {
379             bind(String.class);
380             bind(HashEqualsTester.class).toInstance(a);
381             bind(HashEqualsTester.class).toInstance(b);
382           }
383         });
384   }
385 
testHashcodeNeverCalledOnProviderInstance()386   public void testHashcodeNeverCalledOnProviderInstance() {
387     final HashEqualsTester a = new HashEqualsTester();
388     a.throwOnHashcode = true;
389     a.equality = "test";
390 
391     final HashEqualsTester b = new HashEqualsTester();
392     b.throwOnHashcode = true;
393     b.equality = "test";
394     Guice.createInjector(
395         new AbstractModule() {
396           @Override
397           protected void configure() {
398             bind(String.class);
399             bind(Object.class).toProvider(a);
400             bind(Object.class).toProvider(b);
401           }
402         });
403   }
404 
405   private static class RealA extends A {}
406 
407   @ImplementedBy(RealA.class)
408   private static class A {}
409 
removeBasicBindings(Collection<Key<?>> bindings)410   private void removeBasicBindings(Collection<Key<?>> bindings) {
411     bindings.remove(Key.get(Injector.class));
412     bindings.remove(Key.get(Logger.class));
413     bindings.remove(Key.get(Stage.class));
414   }
415 
416   private static class ThrowingModule extends AbstractModule {
417     @Override
configure()418     protected void configure() {
419       bind(Foo.class)
420           .toInstance(
421               new Foo() {
422                 @Override
423                 public boolean equals(Object obj) {
424                   throw new RuntimeException("Boo!");
425                 }
426 
427                 @Override
428                 public int hashCode() {
429                   throw new RuntimeException("Boo!");
430                 }
431               });
432     }
433   }
434 
435   private abstract static class FooModule extends AbstractModule {
436     protected final FooImpl foo;
437     protected final Provider<Foo> pFoo;
438     protected final Class<? extends Provider<? extends Foo>> pclFoo;
439     protected final Class<? extends Foo> clFoo;
440     protected final Constructor<FooImpl> cFoo;
441 
FooModule( FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo, Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo)442     FooModule(
443         FooImpl foo,
444         Provider<Foo> pFoo,
445         Class<? extends Provider<? extends Foo>> pclFoo,
446         Class<? extends Foo> clFoo,
447         Constructor<FooImpl> cFoo) {
448       this.foo = foo;
449       this.pFoo = pFoo;
450       this.pclFoo = pclFoo;
451       this.clFoo = clFoo;
452       this.cFoo = cFoo;
453     }
454   }
455 
456   private static class FailedModule extends FooModule {
FailedModule( FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo, Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo)457     FailedModule(
458         FooImpl foo,
459         Provider<Foo> pFoo,
460         Class<? extends Provider<? extends Foo>> pclFoo,
461         Class<? extends Foo> clFoo,
462         Constructor<FooImpl> cFoo) {
463       super(foo, pFoo, pclFoo, clFoo, cFoo);
464     }
465 
466     @Override
configure()467     protected void configure() {
468       // InstanceBinding
469       bind(Foo.class).toInstance(foo);
470 
471       // ProviderInstanceBinding
472       bind(Foo.class).toProvider(pFoo);
473 
474       // ProviderKeyBinding
475       bind(Foo.class).toProvider(pclFoo);
476 
477       // LinkedKeyBinding
478       bind(Foo.class).to(clFoo);
479 
480       // ConstructorBinding
481       bind(Foo.class).toConstructor(cFoo);
482     }
483 
484     @Provides
foo()485     Foo foo() {
486       return null;
487     }
488   }
489 
490   private static class FailingProviderModule extends AbstractModule {
491 
492     @Provides
foo()493     Foo foo() {
494       return null;
495     }
496   }
497 
498   private static class SimpleProviderModule extends AbstractModule {
499 
500     @Provides
501     @Named("providerMethod")
foo()502     Foo foo() {
503       return null;
504     }
505 
506     @Override
equals(Object obj)507     public boolean equals(Object obj) {
508       return obj.getClass() == getClass();
509     }
510   }
511 
512   private static class SimpleModule extends FooModule {
SimpleModule( FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo, Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo)513     SimpleModule(
514         FooImpl foo,
515         Provider<Foo> pFoo,
516         Class<? extends Provider<? extends Foo>> pclFoo,
517         Class<? extends Foo> clFoo,
518         Constructor<FooImpl> cFoo) {
519       super(foo, pFoo, pclFoo, clFoo, cFoo);
520     }
521 
522     @Override
configure()523     protected void configure() {
524       // InstanceBinding
525       bind(Foo.class).annotatedWith(named("instance")).toInstance(foo);
526 
527       // ProviderInstanceBinding
528       bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo);
529 
530       // ProviderKeyBinding
531       bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo);
532 
533       // LinkedKeyBinding
534       bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo);
535 
536       // UntargettedBinding / ConstructorBinding
537       bind(FooImpl.class);
538 
539       // ConstructorBinding
540       bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo);
541 
542       // ProviderMethod
543       // (reconstructed from an Element to ensure it doesn't get filtered out
544       //  by deduplicating Modules)
545       install(Elements.getModule(Elements.getElements(new SimpleProviderModule())));
546     }
547   }
548 
549   private static class ScopedModule extends FooModule {
550     private final Scope scope;
551 
ScopedModule( Scope scope, FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo, Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo)552     ScopedModule(
553         Scope scope,
554         FooImpl foo,
555         Provider<Foo> pFoo,
556         Class<? extends Provider<? extends Foo>> pclFoo,
557         Class<? extends Foo> clFoo,
558         Constructor<FooImpl> cFoo) {
559       super(foo, pFoo, pclFoo, clFoo, cFoo);
560       this.scope = scope;
561     }
562 
563     @Override
configure()564     protected void configure() {
565       // ProviderInstanceBinding
566       bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope);
567 
568       // ProviderKeyBinding
569       bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope);
570 
571       // LinkedKeyBinding
572       bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope);
573 
574       // UntargettedBinding / ConstructorBinding
575       bind(FooImpl.class).in(scope);
576 
577       // ConstructorBinding
578       bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope);
579     }
580   }
581 
582   private static class AnnotatedScopeModule extends FooModule {
583     private final Class<? extends Annotation> scope;
584 
AnnotatedScopeModule( Class<? extends Annotation> scope, FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo, Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo)585     AnnotatedScopeModule(
586         Class<? extends Annotation> scope,
587         FooImpl foo,
588         Provider<Foo> pFoo,
589         Class<? extends Provider<? extends Foo>> pclFoo,
590         Class<? extends Foo> clFoo,
591         Constructor<FooImpl> cFoo) {
592       super(foo, pFoo, pclFoo, clFoo, cFoo);
593       this.scope = scope;
594     }
595 
596     @Override
configure()597     protected void configure() {
598       // ProviderInstanceBinding
599       bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope);
600 
601       // ProviderKeyBinding
602       bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope);
603 
604       // LinkedKeyBinding
605       bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope);
606 
607       // UntargettedBinding / ConstructorBinding
608       bind(FooImpl.class).in(scope);
609 
610       // ConstructorBinding
611       bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope);
612     }
613   }
614 
615   private static interface Foo {}
616 
617   private static class FooImpl implements Foo {
618     @Inject
FooImpl()619     public FooImpl() {}
620 
cxtor()621     private static Constructor<FooImpl> cxtor() {
622       try {
623         return FooImpl.class.getConstructor();
624       } catch (SecurityException e) {
625         throw new RuntimeException(e);
626       } catch (NoSuchMethodException e) {
627         throw new RuntimeException(e);
628       }
629     }
630   }
631 
632   private static class FooProvider implements Provider<Foo> {
633     @Override
get()634     public Foo get() {
635       return new FooImpl();
636     }
637   }
638 
639   private static class Bar implements Foo {
640     @Inject
Bar()641     public Bar() {}
642 
cxtor()643     private static Constructor<Bar> cxtor() {
644       try {
645         return Bar.class.getConstructor();
646       } catch (SecurityException e) {
647         throw new RuntimeException(e);
648       } catch (NoSuchMethodException e) {
649         throw new RuntimeException(e);
650       }
651     }
652   }
653 
654   private static class BarProvider implements Provider<Foo> {
655     @Override
get()656     public Foo get() {
657       return new Bar();
658     }
659   }
660 
661   private static class HashEqualsTester implements Provider<Object> {
662     private String equality;
663     private boolean throwOnEquals;
664     private boolean throwOnHashcode;
665 
666     @Override
equals(Object obj)667     public boolean equals(Object obj) {
668       if (throwOnEquals) {
669         throw new RuntimeException();
670       } else if (obj instanceof HashEqualsTester) {
671         HashEqualsTester o = (HashEqualsTester) obj;
672         if (o.throwOnEquals) {
673           throw new RuntimeException();
674         }
675         if (equality == null && o.equality == null) {
676           return this == o;
677         } else {
678           return Objects.equal(equality, o.equality);
679         }
680       } else {
681         return false;
682       }
683     }
684 
685     @Override
hashCode()686     public int hashCode() {
687       if (throwOnHashcode) {
688         throw new RuntimeException();
689       } else {
690         return super.hashCode();
691       }
692     }
693 
694     @Override
get()695     public Object get() {
696       return new Object();
697     }
698   }
699 }
700