Java scoping rules and inner classes
Asked Answered
T

6

5

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?

Tedi answered 31/1, 2011 at 5:54 Comment(8)
Look at the reference card of this post (at the bottom of the article) that summarizes the scoping rules.Jibe
Please (1) tone down and (2) clarify your question. The 'crazy Java scoping rules' you are asking about are identical to 'lexical scoping' as in C++. You will have to explain what you mean by "the 'public static void' nonsense": this is another feature which also exists in C++. And "the 'public static private' stuff floating around" doesn't exist: this is just a contradiction in terms.Chinch
Pretty sure the OP comes from a scripting language background with true lexical scoping (e.g., JavaScript, Ruby) and less emphasis on modifier keywords all over the place. Just saying.Spiraea
@EJP: The question is pretty clear. Access modifiers interact with the scope and it's not clear how access modifiers change lexical scope for instances and inner classes.Tedi
@davidk01: I disagree. He doesn't mention access modifiers at all, just scoping rules. And 'crazy', 'nonsense' etc don't endear either.Chinch
@EJP: I think 'public static void', 'public static private' qualifies as mentioning access modifiers. All the qualifier stuff is indeed nonsense because every other programming language manages to do without them and all the ceremonial incantations that Java requires. Anyway I'm not here to argue with you about the demerits of Java.Tedi
@davidk01: It qualifies as posting nonsense too.Chinch
Your question is clear and your mood is humanlike. We are not machines, and shouldn't act like one.Anomie
E
18

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.

Erudition answered 31/1, 2011 at 6:3 Comment(7)
This second paragraph is the key difference between static and instance inner classes.Spiraea
This is pretty clear. So if I understood you correctly any kind of variable declared in the outer class regardless of any kind of access modifier is accessible from a non-static inner class. So all static and private variables and methods in the outer classes are accessible from the inner class.Tedi
That's about it. If performance is critical, be aware that there is a slight penalty in both time and memory for an inner class to access protected or private members of the outer class (and vice versa). Once compiled, inner classes (static or not) are treated in the byte code as separate classes. Thus, the compiler has to create accessor functions so that the byte code obeys the access rules.Erudition
@TedHopp Can you extend or implement inner classes/interfaces?Pinxit
@MehdiCharife - Sure, provided visibility constraints aren't violated. See #14534921, for instance, on how to do it.Erudition
@TedHopp Sorry, I didn't frame the question correctly. I saw the post that you linked to but I was wondering if one could write classes extending the inner class without wrapping the extending classes in a outer class.Pinxit
@MehdiCharife - Yes, you can. The trick is that the extending class constructor needs to take an instance of the outer class (or something assignment-compatible with it) as its first argument. See, for example, https://mcmap.net/q/1920671/-extending-an-inner-class-in-java.Erudition
Y
3

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);
}
Young answered 31/1, 2011 at 6:0 Comment(0)
E
3

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.

Eggshaped answered 31/1, 2011 at 6:5 Comment(0)
J
3

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);
Jann answered 12/4, 2018 at 18:36 Comment(0)
S
0

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
Servia answered 21/8, 2013 at 0:17 Comment(0)
M
-2

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

Morrismorrison answered 7/8, 2015 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.