56

I working on a sample problem of over-ridding hashCode and equals method but getting an error: "No enclosing instance of type CustomHashCodeExample is accessible. Must qualify the allocation with an enclosing instance of type CustomHashCodeExample (e.g. x.new A() where x is an instance of CustomHashCodeExample)." I wrote an inner class HashPerson and I am getting this error when I am trying to instantiate this inner class in another method called testHashCodeOverride().

public static void testHashCodeOverride(){   
    System.out.println("\nTest HashCode Override Method");
    System.out.println("==================================\n");

    HashPerson william = new HashPerson("willy");
    HashPerson bill = new HashPerson("willy");          
}

This code works fine, even though I dont see static inner class or instantiation of outer class, confused :(

public class HashCodeExample {

    public static void testHashCodeOverride() {

        HashPerson william = new HashPerson("Willy");
        HashPerson bill = new HashPerson("Willy");
        System.out.println("Hash code for william  = " + william.hashCode());
        System.out.println("Hash code for bill     = " + bill.hashCode());

        HashMap table = new HashMap();
        table.put(william, "Silly");

        if (table.containsKey(william)) {
            System.out.println(table.get(william));
        } else {
            System.out.println("Key " + william + " not found");
        }

        if (table.containsKey(bill)) {
            System.out.println(table.get(bill));
        } else {
            System.out.println("Key " + bill + " not found");
        }


    }

    class HashPerson {
        private static final int HASH_PRIME = 1000003;

        public HashPerson(String name) {
            this.name = name;
        }

        public String toString() {
            return name;
        }

        public boolean equals(Object rhs) {
            if (this == rhs)
                return true;

            // make sure they are the same class
            if (rhs == null || rhs.getClass() != getClass())
                return false;

            // ok, they are the same class. Cast rhs to HashPerson
            HashPerson other = (HashPerson) rhs;

            // our test for equality simply checks the name field
            if (!name.equals(other.name)) {
                return false;
            }

            // if we get this far, they are equal
            return true;
        }
        public int hashCode() {
            int result = 0;
            result = HASH_PRIME * result + name.hashCode();
            return result;
        }
        private String name;

    }
}
shankshera
  • 947
  • 3
  • 20
  • 45
t0mcat
  • 5,511
  • 19
  • 45
  • 58
  • You should really clean up the formatting of the example code and strip it down to the essentials. In its current state this is pretty much unreadable. – MForster Nov 01 '10 at 16:33
  • You can simplify your `hashCode` method to just `return name.hashCode();` – Steve Kuo Nov 01 '10 at 18:46
  • @Jonik: Thanks for cleaning up the code formatting. I don't have enough reputation yet to do that. This leaves me a bit confused, though. As I look at the code, it should produce the same "no enclosing instance" error, because the static method `testHashCodeOverride` wants to instantiate an object of the non-static nested (=inner) class `HashPerson`. – MForster Nov 01 '10 at 19:45
  • @Steve, This is an example that shows how to override hashcode for all scenarios, I was just trying the same on my own. name.hashCode(); would return me the memory address, correct? – t0mcat Nov 02 '10 at 01:18
  • @t3ch `name.hashCode()` returns the hash code of name. Since name is a String the hash is based on the string's text. – Steve Kuo Nov 02 '10 at 03:34
  • @Steve, Thanks :) So is it the concept that immutable objects/classes have a constant hashcode through out? – t0mcat Nov 02 '10 at 12:54
  • Possible duplicate of [Java - No enclosing instance of type Foo is accessible](http://stackoverflow.com/questions/9560600/java-no-enclosing-instance-of-type-foo-is-accessible) – fabian Mar 04 '16 at 00:18

3 Answers3

150

I think you want to declare the HashPerson class as static. Otherwise it can only be instantiated in the context of the containing class, either in a method of the containing class or using code like this:

ContainingClass container = new ContainingClass();
HashPerson william = container.new HashPerson("willy");

Actually, my rule-of-thumb is to make any nested class static, unless I have a special reason not to. This is also more efficient, because non-static nested classes (called inner classes) always contain an implicit reference to the containing object.

MForster
  • 8,806
  • 5
  • 28
  • 32
  • Thanks MForster, The place I am confused at, I have a sample program which is written exactly the same way I am doing it here and in that code, inner class is not static and neither they are making an instance of containing class. Am I missing something in that code? "Attaching code in my question" – t0mcat Nov 01 '10 at 16:21
  • Are they creating the instance within a method of the containing class? – MForster Nov 01 '10 at 16:24
  • Maybe I am not reading the code correctly. Just posted the actual code. – t0mcat Nov 01 '10 at 16:25
  • >> because non-static nested classes (called inner classes) always contain an implicit reference to the containing object. MForster, Why is bad for an inner class to have reference to the containing class? – t0mcat Nov 01 '10 at 16:27
  • It needs memory. Your posted code is not readable by the way. But it looks to me as if the HashPerson class is a top-level class in that case, not a nested class. – MForster Nov 01 '10 at 16:28
  • inner classes are a great way IMO to deal with singleton dependency injection in a non-singleton. You have a singleton factory class with your singleton dependencies that creates inner classes (often with an interface) without having constructor spaghetti. Another use is to wrap private methods that all use the same parameters to again reduce spaghetti. e.g. a class that represents an iteration in a loop or sequence, do you really want to have to pass in stuff to the contructor for some private class with limited scope? – Novaterata Jul 30 '21 at 18:47
  • @Novaterata, what you said is true. It falls into the exception that I made above ("unless I have a special reason not to"). But it also doesn't apply to the code in the question. – MForster Aug 20 '21 at 10:06
10

You need to either make your inner class static, or refer to it through an instance of the outer class. Most likely you just want to make your inner class static.

Non-static members of a class (variables, methods, inner classes) are per instance of the class. Therefore, when accessing non-static members from a static context (such as a static method like testHashCodeOverride), you need to specify an instance of the enclosing class.

oksayt
  • 4,333
  • 1
  • 22
  • 41
  • Hi oksayt, so in most cases we should make the inner class static? What is the preferred way? Accessing via instance of outer class or static? – t0mcat Nov 01 '10 at 16:17
  • Don't use inner classes for public APIs. Inner classes were added to have closures and anonymous classes. – Aaron Digulla Nov 01 '10 at 16:20
  • By default, top-level classes are static, but inner classes are non-static. If you're making an inner class just for code organization purposes, then making it `static` and treating it like a standalone class (with the option of limiting visibility) is preferred. If you need the inner class to have access to the non-static members of its enclosing class, then you should make it non-static. – oksayt Nov 01 '10 at 16:23
2

As i can see there could be different possible ways to instantiate the Inner Classes

  1. Static Inner Class : When Inner class is static, let say code looks like as describe.

    class OuterClass 
    {
        static int outer_x = 10;
        int outer_y = 20;
        // static nested class 
        static class StaticNestedClass {
            void display() {
    
            }
        }
    }
    
    OuterClass.StaticNestedClass nestedObject =
     new OuterClass.StaticNestedClass();
    

or Just this could be sufficient for static classes

 new StaticNestedClass();
  1. Local inner Classes (Non Static) : Inner Classes which are not static, one good thing with local inner classes that they can access all private data members of enclosed class.

    OuterClass outerObject = new OuterClass(); 
    OuterClass.InnerClass innerObject = outerObject.new InnerClass();
    
  2. Anonymous Inner Class (implementing Interface) : This type of classes generally hidden, One can't directly see the Class{...} block in code , That is why known as Anonymous Inner Class. Here describes how to instantiate it in case inner class implementing an interface Runnable Interface.

    Runnable r = new Runnable() 
    { 
      //This is Anonymous Class
      public void run() {
        System.out.println("Child Thread");
      }
    };
    
  3. Anonymous Inner Class (Extending One Class):We can have an anonymous inner class that extends a class, Here i am taking example of Thread Class,

    Thread t = new Thread(new Runnable() 
    {
      //Anonymous Inner class
    public void run() {
        System.out.println("Child Thread");
    }
    });
    
  4. Anonymous Inner class that defines inside method/constructor argument : Inner Classes could be define within methods as well, here giving example how can we define and instantiate it within argument

    public static void main(String[] args) 
    { 
    //Here we are using Anonymous Inner class 
    //that define inside argument, here constructor argument 
    Thread t = new Thread(new Runnable() 
    { 
        public void run() 
        { 
            System.out.println("Child Thread"); 
        } 
    });
    t.start();
    
dinesh kandpal
  • 738
  • 7
  • 16