關於內部類

對內部類用的少,基本上都有點陌生了。今天看到一個博客感覺還不錯就轉了過來。先謝謝博主!!!

1.關於內部類的說明
1)在一個類中定義另外一個類,這個類就叫做內部類(inner class) 。內部類的定義和普通類的定義沒什麼區別,它可以直接訪問和引用它的外部類的所有變量和方法(包括private),就像外部類中的其他非static成員的功能一樣。區別是,外部類只能聲明爲public和default,而內部類可以聲明爲private和protected。 中國自學編程網 www.zxbc.cn
 
2)當我們建立一個inner class時,其對象就擁有了與外部類對象之間的一種關係,這是通過一個特殊的this reference形成的,當內部類的成員方法中訪問某個變量/方法時,如果在該方法和內部類中都沒有定義過這個變量,調用就會被傳遞給內部類中保存的那個外部類對象的引用(OuterClass.this),通過那個外部類對象的引用去調用這個變量。
 
2.內部類變量訪問
2.1在main中直接從外部類調用內部類的方法
package org.zj.sample;
class Outer {
    private int index = 100;
    class Inner {
         private int index = 50;
         void print() {
           int index = 30;
           System.out.println(index); // 30
           System.out.println(this.index); // 50
           System.out.println(Outer.this.index); // 100
         }
}
 
    void print() {
         Inner inner = new Inner();//得到內部類的引用
         inner.print();
    }
}
 
class Test {
    public static void main(String[] args) {
         Outer outer = new Outer();
         outer.print();
    }
}

該示例程序列出了重名成員變量分佈的3種情況。
訪問內部類方法中的變量:
System.out.println(index);

訪問內部類中的成員變量:
System.out.println(this.index);

訪問所在外部類的成員變量:
System.out.println(Outer.this.index);

 
2.2在main中顯式返回內部類引用
package org.zj.example;
class Outer {
    private int index = 100;
class Inner {
         private int index = 50;
         void print() {
           int index = 30;
           System.out.println(index); // 30
           System.out.println(this.index); // 50
           System.out.println(Outer.this.index); // 100
         }
}
 
    Inner getInner() {
         return new Inner();//返回一個內部類的引用
    }
}
 
class Test {
    public static void main(String[] args) {
         Outer outer = new Outer();
         Outer.Inner inner = outer.getInner();
         inner.print();
    }
}

 
2.3當main方法在Outer類內部
package org.zj.sample1;
class Outer {
    private int index = 100;
    class Inner {
         private int index = 50;
         void print() {
           int index = 30;
           System.out.println(index); // 30
           System.out.println(this.index); // 50
           System.out.println(Outer.this.index); // 100
         }
    }
 
    Inner getInner() {
         return new Inner();
    }
 
    public static void main(String[] args) {
Outer outer = new Outer();
         Inner inner = outer.getInner(); // 注意此處變化
         inner.print();
    }
}

 
2.4在main方法中直接產生內部類對象
package org.zj.sample2;
class Outer {
    private int index = 100;
    class Inner {
         private int index = 50;
         void print() {
           int index = 30;
           System.out.println(index); // 30
           System.out.println(this.index); // 50
           System.out.println(Outer.this.index); // 100
         }
}
}
 
class Test {
    public static void main(String[] args) {
         Outer outer = new Outer();
         Outer.Inner inner = outer.new Inner(); // 注意此處變化
         inner.print();
    }
}

 
2.5在方法中定義內部類
在方法中定義的內部類只能訪問方法中的final類型的局部變量,因爲用final定義的局部變量相當於是一個常量,它的生命週期超出方法運行的生命週期。而且方法體中的內部類不能有訪問說明符。
package org.zj.sample;
class InOut {
    String str=new String("Between");
    public void amethod(final int aArgs){
         class Inner{
        public Inner(){
          System.out.println("This is Inner.");//此句可看出它與匿名內部類用法的不同。
        }
           public void sayHello(){
System.out.println(str);
                System.out.println(aArgs);
           }
       }
    Inner inner=new Inner();//此句必須放在定義類Inner的後面
       inner.sayHello();
    }
    
    public static void main(String[] args){
         InOut inOut=new InOut();
         inOut.amethod(33);
    }
}

在方法體中使用內部類可以使用一個已命名的構造子,或重載構造子。而匿名內部類只能用於實例初始化。
 
3.內部類的繼承
當一個類繼承自一個內部類時,缺省的構造器不可用。必須使用如下語法:
enclosingClassReference.super();(見下例綠色部分)
package org.zj.sample;
class WithInner{
    class Inner{
         public void sayHello(){
           System.out.println("Hello.");
         }
    }
}
public class InheritInner extends WithInner.Inner {
    InheritInner(WithInner wi){
         wi.super();
    }
    public static void main(String[] args) {
         WithInner wi=new WithInner();
         InheritInner ii=new InheritInner(wi);
         ii.sayHello();
    }
}

 
結果:
Hello.
 
4.匿名內部類
未使用匿名內部類的情況:這裏單獨寫了一個內部類Inner。
package org.zj.example;
abstract class A{
    abstract public void sayHello();
}
 
class Outer {
    public static void main(String[] args){
       class Inner extends A{
           public void sayHello(){
   System.out.println("Hello!");
           }
       }
       new Outer().callInner(new Inner());
    }
    
    public void callInner(A a){
         a.sayHello();
    }
}

使用匿名內部類的情況:直接在new A()中給出Inner的定義。
package org.zj.example;
abstract class A{
    abstract public void sayHello();
}
 
class Outer {
    public static void main(String[] args){
       new Outer().callInner(new A(){
           public void sayHello(){
              System.out.println("Hello!");
           }
       });
    }
    
    public void callInner(A a){
         a.sayHello();
    }
}

 
5.內部類的2種特殊用法
一個類從另一個類派生出來,又要實現一個接口。但在接口中定義的方法與父類中定義的方法的意義不同,則可以利用內部類來解決這個問題。
package org.zj.sample;
interface Machine {
    void run();
}
 
class Person {
    void run() {
         System.out.println("run");
    }
}
 
class Robot extends Person {
    private class MachineHeart implements Machine {
         public void run() {
           System.out.println("heart run");
         }
    }
 
    Machine getMachine() {
         return new MachineHeart();
    }
}
 
class Test {
    public static void main(String[] args) {
         Robot robot = new Robot();
         Machine m = robot.getMachine();
         m.run();
         robot.run();
    }
}

在Robot類內部使用內部類MachineHeart來實現接口Machine的run方法。同時Robot類又繼承了父類Person的run方法。如果不使用內部類MachineHeart而使Robot直接實現接口Machine,則該如何調用父類的run方法?
 
利用內部類可解決c++中多重繼承所解決的問題
package org.zj.example;
class A {
    void fn1() {
       System.out.println("It’s fn1.");
    }
}
 
abstract class B {
    abstract void fn2();
}
 
class C extends A {
    B getB() {
       return new B() {
           public void fn2() {
              System.out.println("It’s fn2.");
           }
       };
    }
}
 
class Test {
    public static void main(String[] args) {
       C c = new C();
       c.fn1();
       c.getB().fn2();
    }
}

類C既要繼承類A又要繼承類B,則可將類B的定義放入類C內部,使之成爲內部類。
 
6.我們爲什麼使用內部類
這是對上一章節兩種用法的總結,可結合上一章節的兩個實例分析。
1)  當我們需要在某一情形下實現一個接口,而在另一情形下又不需要實現這個接口時,我們可以使用內部類來解決這一問題。讓內部類來實現這個接口。
2)  內部類有效的解決了多重繼承的問題。


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/armyjian/archive/2007/11/05/1867936.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章