Java中的內(nèi)部類

          1. 什么是內(nèi)部類       

            內(nèi)部類是指在一個(gè)外部類的內(nèi)部再定義一個(gè)類。
            內(nèi)部類可以是靜態(tài)static的,也可用public,default,protected和private修飾。(而外部頂級(jí)類即類名和文件名相同的只能使用public和default)。
            注意:內(nèi)部類是一個(gè)編譯時(shí)的概念,一旦編譯成功,就會(huì)成為完全不同的兩類。對(duì)于一個(gè)名為Outer的外部類和其內(nèi)部定義的名為Inner的內(nèi)部類。編譯完成后出現(xiàn)Outer.class和Outer$Inner.class兩類。所以內(nèi)部類的成員變量/方法名可以和外部類的相同。
            java內(nèi)部類分為: 成員內(nèi)部類、靜態(tài)嵌套類、局部內(nèi)部類、匿名內(nèi)部類 。

          2. 內(nèi)部類的共性

            (1)、內(nèi)部類仍然是一個(gè)獨(dú)立的類,在編譯之后內(nèi)部類會(huì)被編譯成獨(dú)立的.class文件,但是前面冠以外部類的類名和$符號(hào) 。
            (2)、內(nèi)部類不能用普通的方式訪問。內(nèi)部類是外部類的一個(gè)成員,因此內(nèi)部類可以自由地訪問外部類的成員變量,無論是否是private的 。
            (3)、內(nèi)部類聲明成靜態(tài)的,就不能隨便的訪問外部類的成員變量了,此時(shí)內(nèi)部類只能訪問外部類的靜態(tài)成員變量 。
          3. 成員內(nèi)部類
            public class Outer {
                private int a = 10;
                private int b = 15;
                
                public void print() {
                    System.out.println("Outer.a="+this.a);
                }
                
                public int add(int i,int j) {
                    return i+j;
                }
                
                class Inner {        
                    private int a = 20;
                    private int c = b;
                    
                    public void print() {
                        //內(nèi)部類訪問外部類中的同名成員變量
                        System.out.println("Outer.a="+Outer.this.a);    
                        System.out.println("Inner.a="+this.a);
                        System.out.println("a="+a);
                        //內(nèi)部類中可以直接訪問外部類的成員變量和方法(內(nèi)部類對(duì)象持有指向外部類對(duì)象的引用。)
                        System.out.println("c="+c);
                        System.out.println("c+1="+add(c,1));
                    }
                }
                
                public static void main(String[] args) {
                    Outer outer = new Outer();
                    outer.print();
                    //內(nèi)部類對(duì)象的創(chuàng)建依賴于外部類對(duì)象;
                    outer.new Inner().print();   
                }
            }
            這個(gè)類編譯后出現(xiàn)Outer.class和Outer$Inner.class兩個(gè)class文件。編譯后成為兩個(gè)獨(dú)立的類,
            因此,內(nèi)部類中可以定義與外部類中同名的屬性和方法。

            成員內(nèi)部類,就是作為外部類的成員,與外部類的屬性、方法并列。可以直接使用外部類的所有成員和方法,即使是private的。
            同時(shí)外部類要訪問內(nèi)部類的所有成員變量和方法,則需要通過內(nèi)部類的對(duì)象來獲取。
            要注意的是,成員內(nèi)部類不能含有static的變量和方法。因?yàn)槌蓡T內(nèi)部類需要先創(chuàng)建了外部類,才能創(chuàng)建它自己的

          4. 局部內(nèi)部類
            局部內(nèi)部類,是指內(nèi)部類定義在方法和作用域內(nèi)。
            (1)、定義在方法內(nèi)
                
            public class Teacher {
                
                private String name;
                private int age;    
                
                public void teach() {
                    final String str = "I'm a teacher!";
                    class EnglishTeacher {
                        public void teachEnglish() {
                            System.out.println("My name is "+name);
                            System.out.println("I'm "+age);
                            System.out.println(str);
                            System.out.println("I teach English");
                            
                        }
                    }
                    
                    EnglishTeacher englishTeacher = new EnglishTeacher();
                    englishTeacher.teachEnglish();
                }

                /**
                 * 
            @param args
                 
            */
                public static void main(String[] args) {
                    // TODO Auto-generated method stub
                    Teacher teacher = new Teacher();
                    teacher.name = "張三";
                    teacher.age = 35;
                    teacher.teach();
                }
            } 


            (2)、定義在作用域內(nèi)
             

            public class Teacher1 {

                private String name;
                private int age;    
                
                public void teach(String course) {
                    final String str = "I'm a teacher!";
                    System.out.println(str);
                    if("English".equals(course)) {
                        class EnglishTeacher {
                            public void teachEnglish() {
                                System.out.println("My name is "+name);
                                System.out.println("I'm "+age);
                                System.out.println("I teach English");
                            }
                        }
                        
                        EnglishTeacher englishTeacher = new EnglishTeacher();
                        englishTeacher.teachEnglish();
                    }        
                }
                /**
                 * 
            @param args
                 
            */
                public static void main(String[] args) {
                    // TODO Auto-generated method stub
                    Teacher1 teacher = new Teacher1();
                    teacher.name = "張三";
                    teacher.age = 35;
                    teacher.teach("English");
                }

            }
                

            (1)、局部內(nèi)部類只能在定義該內(nèi)部類的方法內(nèi)實(shí)例化,不可以在此方法外對(duì)其實(shí)例化。
            (2)、局部內(nèi)部類對(duì)象不能使用該內(nèi)部類所在方法的非final局部變量。
            (3)、局部內(nèi)部類的地位和方法內(nèi)的局部變量的位置類似,因此不能修飾局部變量的修飾符也不能修飾局部內(nèi)部類,
                   譬如public、private、protected、static、transient等
            因?yàn)榉椒ǖ木植孔兞课挥跅I希淮嬖谟谠摲椒ǖ纳趦?nèi)。當(dāng)一個(gè)方法結(jié)束,其棧結(jié)構(gòu)被刪除,局部變量成為歷史。但是該方法結(jié)束之后,在方法內(nèi)創(chuàng)建的內(nèi)部類對(duì)象可能仍然存在于堆中!例如,如果對(duì)它的引用被傳遞到其他某些代碼,并存儲(chǔ)在一個(gè)成員變量內(nèi)。正因?yàn)椴荒鼙WC局部變量的存活期和方法內(nèi)部類對(duì)象的一樣長,所以內(nèi)部類對(duì)象不能使用它們。
          5. 靜態(tài)嵌套類


            public class StaticOuter {

                private int a = 10;
                private static int b = 15;
                
                static class StaticInner {
                    public static void print() {
                        System.out.println("b="+b);
                    }
                    
                    void print1() {
                        System.out.println("b="+b);
                    }
                }
                /**
                 * 
            @param args
                 
            */
                public static void main(String[] args) {
                    // TODO Auto-generated method stub
                    StaticOuter.StaticInner.print();
                    new StaticOuter.StaticInner().print1();
                }

            }

            嵌套類和普通的內(nèi)部類還有一個(gè)區(qū)別:普通內(nèi)部類不能有static數(shù)據(jù)和static屬性,也不能包含嵌套類,但嵌套類可以。
            而嵌套類不能聲明為private,一般聲明為public,方便調(diào)用。

            在靜態(tài)方法中定義的內(nèi)部類也是StaticNested Class,這時(shí)候不能在類前面加static關(guān)鍵字,靜態(tài)方法中的StaticNested Class與
            普通方法中的內(nèi)部類的應(yīng)用方式很相似,它除了可以直接訪問外部類中的static的成員變量,還可以訪問靜態(tài)方法中的局部變量,
            但是,該局部變量前必須加final修飾符。

          6. 匿名內(nèi)部類

          7. 匿名內(nèi)部類就是沒有名字的內(nèi)部類。什么情況下需要使用匿名內(nèi)部類?如果滿足下面的一些條件,使用匿名內(nèi)部類是比較合適的:
            ·只用到類的一個(gè)實(shí)例 。
            ·類在定義后馬上用到。
            ·類非常小(SUN推薦是在4行代碼以下)
            ·給類命名并不會(huì)導(dǎo)致你的代碼更容易被理解。
            在使用匿名內(nèi)部類時(shí),要記住以下幾個(gè)原則:
            ·匿名內(nèi)部類不能有構(gòu)造方法。
            ·匿名內(nèi)部類不能定義任何靜態(tài)成員、靜態(tài)方法。
            ·匿名內(nèi)部類不能是public,protected,private,static。
            ·只能創(chuàng)建匿名內(nèi)部類的一個(gè)實(shí)例。
            ·一個(gè)匿名內(nèi)部類一定是在new的后面,用其隱含實(shí)現(xiàn)一個(gè)接口或?qū)崿F(xiàn)一個(gè)類。
            ·因匿名內(nèi)部類為局部內(nèi)部類,所以局部內(nèi)部類的所有限制都對(duì)其生效。

            (1)、繼承式的匿名內(nèi)部類

            public class Singer {
                
                public void sing() {
                    System.out.println("Sing a song");
                }

                /**
                 * 
            @param args
                 
            */
                public static void main(String[] args) {
                    // TODO Auto-generated method stub

                    Singer singer = new Singer() {

                        @Override
                        public void sing() {
                            // TODO Auto-generated method stub
                            System.out.println("Sing a popular song");
                        }
                        
                    };
                    singer.sing();
                }

            }

            輸出結(jié)果:Sing a popular song

            (2)、接口式的匿名內(nèi)部類


            public interface Programmer {
                
                public void code();

            }



            public class TestProgrammer {

                /**
                 * 
            @param args
                 
            */
                public static void main(String[] args) {
                    // TODO Auto-generated method stub
                    Programmer javaProgrammer = new Programmer() {

                        @Override
                        public void code() {
                            // TODO Auto-generated method stub
                            System.out.println("Java programmer");
                        }
                    };

                    javaProgrammer.code();
                    
                    Programmer phpProgrammer = new Programmer() {

                        @Override
                        public void code() {
                            // TODO Auto-generated method stub
                            System.out.println("Php programmer");
                        }
                    };

                    phpProgrammer.code();
                }

            }

            (3)、參數(shù)式的匿名內(nèi)部類


            public interface Programmer {
                
                public void code();

            }




            public class TestProgrammer1 {

                public void testCode(Programmer p) {
                    p.code();
                }
                
                /**
                 * 
            @param args
                 
            */
                public static void main(String[] args) {
                    // TODO Auto-generated method stub
                    TestProgrammer1 testProgrammer1 = new TestProgrammer1();
                    testProgrammer1.testCode(new Programmer() {
                        
                        @Override
                        public void code() {
                            // TODO Auto-generated method stub
                            System.out.println("testing code");
                        }
                    });
                }

            }


          8. 為什么需要內(nèi)部類

          9. 典型的情況是,內(nèi)部類繼承自某個(gè)類或?qū)崿F(xiàn)某個(gè)接口,內(nèi)部類的代碼操作創(chuàng)建其的外圍類的對(duì)象。所以你可以認(rèn)為內(nèi)部類提供了某種進(jìn)入其外圍類的窗口。
            使用內(nèi)部類最吸引人的原因是:
            每個(gè)內(nèi)部類都能獨(dú)立地繼承自一個(gè)(接口的)實(shí)現(xiàn),所以無論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn),對(duì)于內(nèi)部類都沒有影響。如果沒有內(nèi)部類提供的可以繼承多個(gè)具體的或抽象的類的能力,一些設(shè)計(jì)與編程問題就很難解決。從這個(gè)角度看,內(nèi)部類使得多重繼承的解決方案變得完整。接口解決了部分問題,而內(nèi)部類有效地實(shí)現(xiàn)了“多重繼承”。

          posted on 2014-08-01 17:34 小羅 閱讀(201) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          相冊(cè)

          收藏夾

          Web Framework

          常上的技術(shù)網(wǎng)站

          查找資料的java網(wǎng)站

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 那坡县| 桑植县| 昌宁县| 新田县| 府谷县| 东港市| 明溪县| 庐江县| 云阳县| 景谷| 措勤县| 米泉市| 枝江市| 乾安县| 霸州市| 康马县| 周口市| 长治县| 田林县| 五常市| 荔浦县| 翼城县| 绥宁县| 和平区| 宜黄县| 荣昌县| 乐昌市| 天柱县| 日喀则市| 辉南县| 晋城| 四子王旗| 忻州市| 前郭尔| 江口县| 弋阳县| 临漳县| 城市| 乌兰察布市| 黄石市| 永年县|