废话不说 ,上代码。
package innerClass;class Aa{ 
void m(){
System.out.println("outer");

}  public class innerClass { 
public static void main(String[] args) { 
new innerClass().go();  } 
void go(){ 
new Aa().m(); 
class Aa{
void m(){
System.out.println("inner");
}


class Aa{
void m(){
System.out.println("middle");
}

} 请问 最终结果为什么是 middle 请高手逐行注释解释。

解决方案 »

  1.   

    你记住一句话:内部类是个编译概念,也就是说一切关于内部类的东西都是编译时就已经确定的。如何证明这句话呢?很简单!你去编译下你的这个java文件,按理说应该有3个对应于Aa类的class文件,但是你只能找到2个,他们的名字分别是:TestInners$Aa.class和TestInners$1Aa.class。也就是说,你go()方法里定义的那个内部类是不可见的,因为在编译时go()还没有执行,go方法是运行期执行的。然后一点就是就近原则吧  这样你就可以理解为啥是打印middle了个人理解,等楼下的意见。
      

  2.   

    按编译的时间顺序
    首先加载的是InnerClass内
    包括它的成员变量,成员方法go()和内部类Aa
    在运行到go()中的时候
    你new Aa().m()  这个时候 内存中只有InnerClass的内部类Aa
    所以打印的是middle
      

  3.   

    又扯淡,我用楼主的代码编译出来四个class:
    Aa.class,innerClass$1Aa.class,innerClass$Aa.class,innerClass.class
      

  4.   

    刚javac了下,你可能有点疏忽了,还有一个Aa.class他不是内部类,TestInners$Aa.class是innerClass 中go()外的类,TestInners$1Aa.class是go()中的类
      

  5.   

    先帮楼主重新整理排个版package innerClass;
    class Aa
    {
       void m()
       {
          System.out.println("outer");
       }
    }
    public class innerClass
    {
       public static void main(String[] args)
       {
          new innerClass().go();
       }
       void go()
       {
          new Aa().m();
          class Aa
          {
             void m()
             {
                System.out.println("inner");
             }
          }
       }
       class Aa
       {
          void m()
          {
             System.out.println("middle");
          }
       }
    }
      

  6.   

    不要激动  是我搞错了 刚开始把问题搞复杂了 方向也错了 但是为什么会出现这种情况 我认为你的反编译代码不能作为问题的答案 其实还是我开始在另一个帖子里的答复是正确的  是代码顺序问题   也就是说打印Middle的那个Aa是外面的成员内部类,如果你把Middle的内部类注释掉 那么第一句new Aa().m();就会报错;所以这里我认为不是什么就近原则  就是一个简单的代码存在于不存在的问题  如果都存在(两个Aa类都存在)  比如第二句new Aa().m();那可以用就近原则去解释public class TestInners { 
    class Aa{
    void m(){
    System.out.println("Middle");
    }


    void go(){  
    new Aa().m();//输出Middle class Aa{
    void m(){
    System.out.println("Inner");
    }


    new Aa().m();//输出Inner
    }

    public static void main(String[] args) { 
    new TestInners().go();


      

  7.   

    感谢gukuitian的提醒,并且我认为你在《求助:一个关于内部类的问题》里10#的解释 是正确的 如果两个都存在,如我9#所示,那么第一句new Aa().m();是看不见go方法内的Aa类的。对于第二句而言,相当于外面的内部类被方法内的内部类覆盖了,所以输出Inner。相同的道理,请看:int i = 0;
    void go(){ 
    System.out.println(i);//输出0;
    int i = 1;
    System.out.println(i);//输出1;
    }
      

  8.   

    内部类其实和内部变量是一样的,他们都有自己的范围。
    go方法中的内部类的范围是从定义开始,往后。
    验证方法:调整go方法中的两条语句的顺序,你会发现是打印inner class;
    调整结果: void go(){
          class Aa{
                 void m(){
                     System.out.println("inner");
                 }
             } 
            new Aa().m(); 
           
        } 
      

  9.   


    话说回来,其实你打开java类加载选项的话,会发现
    这个类:
    class Aa {
    void m() {
    System.out.println("inner");
    }
    }
    根本都没被加载,说白了就是代码顺序执行和括号作用域的原因。
      

  10.   


    public class Aa {
    void m(){
    System.out.println("outer");
    }}public class TestInner {
    public static void main(String[] args){
    new TestInner().go();
    }
    void go() {
    class Aa{
    void m(){System.out.println("inner"); }
                    }
    new Aa().m();

    }
    class Aa{
            void m(){
                System.out.println("middle");
            }
        } }个人认为,遵循就近原则,从里往外查找
    class中定义变量、方法、内部类都是不分先后顺序的
    但方法中定义变量、内部类,调用某个变量或类是必须在调用之前定义楼主的代码 类 "inner" 定义是无效的
      

  11.   

    为什么3个同名的class,类外部的,类内部的,以及类的方法内部的,运行时会出现这种效果,期待高人回复
      

  12.   

    测试了半天,终于弄明白了
    首先看第一个例子:public class innerClass
    {
       public static void main(String[] args)
       {
          new innerClass().go();
       }
       
       void go()
       {
          new Aa().m();
          class Aa
          {
             void m()
             {
                System.out.println("inner");
             }
          }  
       }如上代码,不能通过编译,因为当编译器执行到new Aa().m();这句话时,由于Aa是方法中的类,暂时还不可见
    可是如果改成:public class innerClass
    {
       public static void main(String[] args)
       {
          new innerClass().go();
       }
       
       void go()
       {
          class Aa
          {
             void m()
             {
                System.out.println("inner");
             }
          }  
          new Aa().m();
       }便可通过编译,运行结果:inner分析1:
    方法内部的类,如果在调用构造器之后才定义该类,该类是不可见的再看第二个例子:public class innerClass
    {
       public static void main(String[] args)
       {
          new innerClass().go();
       }
       
       void go()
       {
          new Aa().m();
          class Aa
          {
             void m()
             {
                System.out.println("inner");
             }
          }  
       }
       
       class Aa
       {
          void m()
          {
             System.out.println("middle");
          }
       }
    }此时以上代码可以通过编译,运行结果:middle
    可是如果把调用构造器的那句话放到方法内部类后面:public class innerClass
    {
       public static void main(String[] args)
       {
          new innerClass().go();
       }
       
       void go()
       {
          class Aa
          {
             void m()
             {
                System.out.println("inner");
             }
          }  
          new Aa().m();
       }
       
       class Aa
       {
          void m()
          {
             System.out.println("middle");
          }
       }
    }这时也可通过编译,运行结果:inner
    进一步做点小改变:public class innerClass
    {
       public static void main(String[] args)
       {
          new innerClass().go();
       }
       
       void go()
       {
          new Aa().m();
          class Aa
          {
             void m()
             {
                System.out.println("inner");
             }
          }  
          new Aa().m();
       }
       
       class Aa
       {
          void m()
          {
             System.out.println("middle");
          }
       }
    }通过编译,运行结果:
    middle
    inner分析2:
    第一段代码,由于方法内部类暂时不可见,所以调用的是方法外部的Aa类的构造器
    第二段代码,由于方法内部类在调用构造器之前已经出现了,根据就近原则,调用的是方法内部Aa类的构造器
    第三段代码,第一个构造器调用时,方法内部类不可见,因此调用方法外部的Aa类构造器,运行到第二个构造器时,方法内部类Aa已经定义,根据就近原则,调用方法内部类Aa的构造器最后看第三个例子,加入外部Aa类:class Aa
    {
       void m()
       {
          System.out.println("outer");
       }
    }public class innerClass
    {
       public static void main(String[] args)
       {
          new innerClass().go();
       }
       
       void go()
       {
          new Aa().m();
          class Aa
          {
             void m()
             {
                System.out.println("inner");
             }
          }  
          new Aa().m();
       }
       
       class Aa
       {
          void m()
          {
             System.out.println("middle");
          }
       }
    }运行结果还是:
    middle
    inner分析3:
    结果与例二的最后一段代码同,说明有同名内部类时,外部同名的类被完全屏蔽了最后的结论:
    1.构造器的调用遵循就近原则,跟构造器最接近的同名类的构造器被调用
    2.如果调用构造器的语句,和同名类定义都在方法内部,则该类定义必须出现在调用构造器之前,否则不可见
      

  13.   

    这太不严格了,你不能仅仅凭几个例子就说你的结论是正确的!
    你最好能从JVM规范上找到依据!或者是某些权威的书上!
    否则,不能叫人信服!
      

  14.   

    且不说语法究竟是怎么会事儿,这个粒子也太糟糕了,几乎违反了一切程序设计的规范:内部类与外嵌类同名,main方法放到内部类里面....嘿嘿!写这样程序的程序员(如果存在),真该回学校重上四年!!!
      

  15.   

    上楼看错了,内部类并没有写MAIN方法,而且非static内部类是不允许写static 方法的,这题倒是,从结论看,局部内部类有作用域的概念,
    非static内部类行为类似方法或属性,但好像没有作用域概念,
    成员内部类会屏蔽掉外面那个类.
      

  16.   

    找到依据了,呵呵
    http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.3Here is an example that illustrates several aspects of the rules given above:class Global {
            class Cyclic {}
            void foo() {
                    new Cyclic(); // create a Global.Cyclic
                    class Cyclic extends Cyclic{}; // circular definition
                    {
                            class Local{};
                            {
                                    class Local{}; // compile-time error
                            }
                            class Local{}; // compile-time error
                            class AnotherLocal {
                                    void bar() {
                                            class Local {}; // ok
                                    }
                            }
                    }
                    class Local{}; // ok, not in scope of prior Local
    }The first statement of method foo creates an instance of the member class Global.Cyclic rather than an instance of the local class Cyclic, because the local class declaration is not yet in scope.