ice world

          There is nothing too difficult if you put your heart into it.
          posts - 104, comments - 103, trackbacks - 0, articles - 0
          標(biāo)題有點(diǎn)長,可能有點(diǎn)語病,先別管那么多!
          首先看下面的這段代碼:
          public class LocalInnerClassTest{
                
          public static void main(String[] args){
                   Outer obj
          =new Outer();          //生成一個外部類對象
                   SuperInner si=obj.outer();        //調(diào)用外部類中的outer()方法,返回一個SuperInner類型對象賦值給si
                  si.m1();             //調(diào)用被覆蓋的方法m1(),輸出:Inner's m1() 20
               }

          }


          /**
          *定義一個接口SuperInner,內(nèi)部定義一個抽象方法m1(),無返回類型
          */

          interface SuperInner{
               
          public void m1();
          }


          /**
          *定義一個類Outer,內(nèi)部只定義一個方法outer(),返回類型為SuperInner
          */

          class Outer{
               
          public SuperInner outer(){
                  
          int a=10;                   //方法中定義一個局部變量a,并賦值為10
                  final int b=20;          //再定義一個final局部變量b,初始化為20

                  
          class Inner implements SuperInner{              //在outer()方法中定義一個局部內(nèi)部類Inner,實(shí)現(xiàn)接口SuperInner
                     public void m1(){    //類中只有一個覆蓋接口SuperInner的方法m1()
                        System.out.println("Inner's m1()"+a);    //編譯報(bào)錯
                        System.out.println("Inner's m1() "+b);    //編譯通過,輸出:Inner's m1() 20
                     }

                 
           }

                  
          return new Inner();
               }

          }




          我們先從主方法開始看代碼的執(zhí)行順序,先生成一個Outer類對象obj,obj調(diào)用本類中方法outer();程序開始跳到outer()方法內(nèi)執(zhí)行程序語句,先后生成局部變量a和b,再定義一個局部內(nèi)部類Inner,返回一個SuperInner類型的對象。將返回的SuperInner類型對象地址傳給SuperInner類型對象si。si再調(diào)用m1()方法,因?yàn)橐呀?jīng)在局部內(nèi)部類中覆蓋了接口中的m1()方法,所以將調(diào)用局部內(nèi)部類中的m1()方法,程序跳到局部內(nèi)部類中m1()方法內(nèi)執(zhí)行程序語句,先輸出一段字符串和a,結(jié)果編譯報(bào)錯,先 將這條程序語句隱藏,執(zhí)行下面的語句,你會發(fā)現(xiàn)編譯通過而且輸出Inner's m1() 20!

          為什么會這樣呢?大家都知道局部變量僅僅在一個范圍內(nèi)有效,在方法調(diào)用完就被內(nèi)存釋放,在Outer類對象obj調(diào)用outer()方法時,a和b才產(chǎn)生,調(diào)用結(jié)束后被內(nèi)存釋放,那么b這個值也就不復(fù)存在了,為什么還會輸出20呢?難道局部變量被final修飾就不會被內(nèi)存釋放而保留?

          其實(shí)有部分操作對于程序員是透明的,那是JAVA語言開發(fā)者的小把戲,在定義a和b 時JVM(JAVA虛擬機(jī))做了程序員看不到的操作,他將b拷貝了一份給局部內(nèi)部類,也就是說JVM在局部內(nèi)部類中定義了一個final int b=20;這個操作程序員是不知道的!當(dāng)調(diào)用m1()方法時輸出的20并不是原來outer()方法中定義的b,而僅僅是JVM拷貝的一個副本。那么為什么a沒被打印出呢?那是因?yàn)镴VM并沒有拷貝它,因?yàn)闆]有final修飾,說明它可以被修改,如果把a(bǔ) 改為 a++,此時JVM就不知道拷貝a還是a++了,所以對于無final修飾的局部變量JVM是不會拷貝傳給局部內(nèi)部類的,自然無法打輸出!

          Feedback

          # re: Java中局部內(nèi)部類可以訪問它所在方法中定義的final修飾的局部變量的合理解釋  回復(fù)  更多評論   

          2011-09-29 08:08 by 分公司
          你說的拷貝我有點(diǎn)疑問,感覺這個是常量池的原因吧
          主站蜘蛛池模板: 玉龙| 剑阁县| 毕节市| 广水市| 宁陵县| 齐齐哈尔市| 东乡县| 高雄市| 新竹县| 和田市| 岑巩县| 嘉鱼县| 丽水市| 沧州市| 府谷县| 田东县| 横峰县| 吴忠市| 招远市| 宣汉县| 卢湾区| 永修县| 班戈县| 介休市| 望江县| 汉寿县| 蕲春县| 梁河县| 长武县| 丁青县| 筠连县| 保山市| 贺州市| 邛崃市| 平顶山市| 广州市| 鸡西市| 江陵县| 响水县| 沙河市| 德令哈市|