Question

All the crazy Java scoping rules are making my head spin and the public static void nonsense isn't helping matters. So far all the programming languages I have used either lexical scoping or some approximation of it without any access modifiers, i.e. inner stuff captures outer stuff and has access to the outer stuff as long as the inner stuff exists.

So how do I make sense of the scoping rules for inner classes in Java? Do they get access to variables declared in the outer class or is there some weird edge cases I have to worry about because of all the public static private stuff floating around?

Was it helpful?

Solution

Static nested classes1 are exactly like external classes except that they have access to all members of the outer class, regardless of access qualifier. They exist apart from any instance of the outer class, so need a reference to an instance in order to access any instance variables or non-static methods of the outer class.

Non-static nested classes (called inner classes) come into existence only in the context of an instance of the outer class. When constructed, they have a second this field automatically generated, which you can access from within the inner class using the syntax Outer.this. Each instance of the inner class is enclosed by a single instance of the outer class. Again, all the access privileges of static nested classes apply to inner classes. But since they already have an instance of the outer class available, they can automatically access instance variables and methods of the outer class.

For a nice (and very detailed) discussion of inner classes and access specifiers, you can read through the Inner Class Specification. It describes, among other things, how a nested class gets access to private members of its outer class(es). A gentler read is the Nested Classes tutorial.

An off-topic aside: Suppose you have this class structure:

public class O {
    public O() { ... }

    public class I { // an inner class
        public I() { ... }
        ...
    }
    ...
}

and you've created an instance of O:

O outer = new O();

Now suppose you want to create an instance of O.I. you can't just use new O.I() because the new instance of I needs to be enclosed by a specific instance of O. For this, Java provides the following syntax:

O.I inner = outer.new O.I();

Then inner will then have its second this field set to refer to outer.

Note that this "qualified new operator" syntax is only used for inner classes; it would be unnecessary (in fact, an error) if I were a static nested class.

1 You'll often come across the phrase "static inner class" (including, embarrassingly, in an earlier version of this answer). This is incorrect terminology. In Java, "inner classes" are specifically non-static nested classes.

OTHER TIPS

You have to differenciate:

  • Static inner classes have access to all static members outside their declaration.
  • Instance inner classes have access to all class members outside their declaration, AND to final fields in the function they are declared in.

Have in mind that a non-static inner class also has a hidden variable with the instance of the outer class, to access the members there. And that all referenced final fields (therefore they must be final) are copied into the inner class in other hidden member variables when the inner class is instantiated.

Example:

public void doStuff(final int a, int b) {
    final int c; // Can be referenced
    int d;       // Cannot be referenced, not final

    executer.execute( new Runnable() {
        public void run() {
            System.out.println("a: "+a+"  c: "+c);
        }
    }

    b++; // Not final, not referencable
    System.out.println(b);
}

I don't know if it helps, but from the java tutorials:

Static Nested Classes

As with class methods and variables, a static nested class is associated with its outer class. And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class — it can use them only through an object reference. Note: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.

Inner Classes [Non-Static Nested class?]

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.

You should check the java tutorial on nested classes.

Rules of the Inner classes in Java

  1. In Java it is possible to define a class inside another class such classes are called nested classes or inner class.
  2. There are 3 types of the Inner classes Instance Inner class, static inner class and anonymous inner class
  3. If the Inner class is declared as instance inner class then it can access all of the members of the outer enclosing class including private members
  4. If the Inner class is declared as static then it can only access the static members of the outer class (including the private static members). But it can NOT access the instance members
  5. Consider that there is a variable x is defined in both the outer class and the instance inner classes then general form for accessing the variable from the inner class is this.x for the inner x and OuterClassname.this.x for the outer x.
  6. You can also define an inner class inside any method or any other block
  7. The general form for instantiating the inner class from outside the outer class is Outer.Inner ob = new Outer.new Inner();
  8. The general form for instantiating the inner class from outside the outer class is (if the inner class is declared as static) Outer.Inner ob = new Outer.Inner();
  9. The Inner classes can be declared with any of the access modifier keywords
  10. If the Inner class is declared as private then it can NOT be instantiated from outside the outer class. Also in this case you can NOT access the members of the Inner class from outside the outer class even you have an object reference and even if the members of the private inner class are declared as public.
  11. If the Inner class is declared as instance inner class then it can also access the superclass members of the outer class through the general statement Outer.super.variable; Outer.super.method(params);

Rules for inner class

  1. Outer class accessed by inner class
  2. Inner class can't be accessed by outer class
  3. The inner class members only used the methods and members within the class only access the fulled information

Method Scoped inner classes:- Can only access the final members of the outer class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top