1

Code description and ouput

In the following code. We have a class TestInners, one inner class A, one method local inner class A and one outer class A.

  1. When we instantiate an object as in new A().m(); the ouput is middle.
  2. In order for the program to output inner we must instantiate the object after the method local inner class A in the gomethod.
  3. If we comment the inner class the program will output outer.

Question

In the code as it is. Why did it output middle? Is there a preference for the inner classes first? then the outer classes? I got confused.


Source code

   class A { void m() { System.out.println("outer"); } }
    
    public class TestInners {
        public static void main(String[] args) {
            new TestInners().go();
        }
        void go() {
            new A().m();
            class A { void m() { System.out.println("inner"); } }
            
        }
        class A { void m() { System.out.println("middle"); } }
    }
Community
  • 1
  • 1
Hani Goc
  • 2,371
  • 5
  • 45
  • 89

1 Answers1

5

Yes, if you shadow symbols with more local definitions, the more local one is chosen. This most frequently happens with method parameters vs instance fields, leading to the famous this.name = name idiom.

In your case, you can get to the outer class by using a fully qualified class name.

But don't name classes like that. Too much confusion for no reason.

Community
  • 1
  • 1
Thilo
  • 257,207
  • 101
  • 511
  • 656
  • 2
    Or said another way: Only ever do that if you're deliberately trying to [obfuscate](https://en.wikipedia.org/wiki/Obfuscation_(software)) the code. – Andreas Nov 24 '16 at 23:03
  • 3
    I would even say "avoid having classes of the same name even across entirely different packages". Something like `java.util.List`, `java.awt.List`, `com.mypackage.List` only messes up auto-completion and makes things harder to read (have to dig out the imports to see what is being used). I think we got a couple of questions caused by List/List (or Data/sql.Date) here on Stackoverflow. – Thilo Nov 24 '16 at 23:06
  • Can you point the JVM spec as well on the same for inner classes ? – Vasu Nov 24 '16 at 23:06
  • 2
    And don't even think about naming classes the same as stuff in `java.lang`. `com.mypackage.String` :-( – Thilo Nov 24 '16 at 23:07
  • @javaguy JVM spec on *what*? – Andreas Nov 24 '16 at 23:07
  • 2
    @javaguy: For language spec on name resolution: http://stackoverflow.com/questions/12931146/using-an-inner-class-name-and-an-object-name-same-in-java?rq=1 – Thilo Nov 24 '16 at 23:08
  • on shadowing behavior – Vasu Nov 24 '16 at 23:08
  • 2
    @javaguy JVM has nothing to do with name shadowing. The JLS (Java Language Specification) will however define such rules. If you open the [JLS](https://docs.oracle.com/javase/specs/jls/se8/html/index.html) and **search** for `shadow`, you'll very quickly find relevant specs (§6.4). This is called *research*, and is a very valuable technique all programmers should learn. – Andreas Nov 24 '16 at 23:10