JDK Hashmap Source Code - Anonymous Inner Classes and Abstract Instantiation?

514 views Asked by At

Problem

I'm trying to understand how Sun implemented the entrySet, keySet and values methods of the HashMap class but I'm coming across code that doesn't make sense to me.

I understand conceptually that these methods return views directly linked to the map.entry list within the HashMap and that they use their own iterators (referencing the central HashMap iterator) for most of their work. My problem though is in understanding how exactly these views are being instantiated in the first place (since they are not a copy but something that sits over top of the actual HashMap list).

Reference

I'm looking at the Source Code located on this site: http://developer.classpath.org/doc/java/util/HashMap-source.html

Here's one of the snippets that is giving me trouble:

 157:   private transient Set<Map.Entry<K, V>> entries;

 594:   public Set<Map.Entry<K, V>> entrySet()
 595:   {
 596:     if (entries == null)
 597:       // Create an AbstractSet with custom implementations of those methods
 598:       // that can be overridden easily and efficiently.
 599:       entries = new AbstractSet<Map.Entry<K, V>>()
 600:       {
 601:         public int size()
 602:         {
 603:           return size;
 604:         }
 605: 
 606:         public Iterator<Map.Entry<K, V>> iterator()
 607:         {
 608:           // Cannot create the iterator directly, because of LinkedHashMap.
 609:           return HashMap.this.iterator(ENTRIES);
 610:         }
 611: 
 612:         public void clear()
 613:         {
 614:           HashMap.this.clear();
 615:         }
 616: 
 617:         public boolean contains(Object o)
 618:         {
 619:           return getEntry(o) != null;
 620:         }
 621: 
 622:         public boolean remove(Object o)
 623:         {
 624:           HashEntry<K, V> e = getEntry(o);
 625:           if (e != null)
 626:             {
 627:               HashMap.this.remove(e.key);
 628:               return true;
 629:             }
 630:           return false;
 631:         }
 632:       };
 633:     return entries;
 634:   }

Questions

  • On line 599 this code is instantiating the AbstractSet class. How is this possible? I've tried to recreate this on my own but I'm getting the expected compile errors.

  • I'm assuming that the public methods in lines 601, 606, 612, 617 and 622 are anonymous inner classes? I've never used this functionality before so I'm iffy on how it works and the only examples I am finding online are fairly simplistic (and mostly involve Swing). I have to assume that line 599 is directly related to the anonymous class but I'm not following how.

I would very much appreciate it if someone could explain this to me! Thanks!

1

There are 1 answers

1
Jon Skeet On BEST ANSWER

On line 599 this code is instantiating the AbstractSet class. How is this possible?

Via an anonymous inner class. It's creating a concrete (but unnamed) subclass of AbstractSet. You can do the same for interfaces. For example:

Runnable runnable = new Runnable() {
    @Override public void run() {
        // Put some code in here...
    }
};

I'm assuming that the public methods in lines 601, 606, 612, 617 and 622 are anonymous inner classes?

No, the whole class is the anonymous inner class. These are implementing the abstract methods of AbstractSet.

I suggest you read the Java tutorial page on anonymous classes.