2016/5/12

匿名內部類別(Anonymous inner class)

例1,static class A就是匿名內部類別,用參考名稱z,去呼叫showMe()。
package anonymous1;
public class Anonymous1 {
    static class A{
        int i =0;
        public String showMe(){
        return "This is X";
        }
    }
    public static void main(String[] args) {
        final String ff="final";        //如果要在內部匿名類別中使用某個方法中的變數,它必須宣告為 final
        A z = new A(){         //匿名類別override showMe方法
            public String showMe(){
                return "This is Z"+i+ff; //可存取A類別的成員
            }
        }; //注意分號別漏掉
        System.out.println(z.showMe());
    }
}
//run:
//This is Z0final
例2,產生匿名內部類別物件後即呼叫其 show() 方法。
package anonymous1;
public class Anonymous1  {
  public static void main(String[] args) {
    final int a= 10;
    (new Object() {  // 匿名類別
       int b =10000;  // 匿名類別的成員
       public void show() {  // 匿名類別的方法
         System.out.println ("匿名類別:");
         System.out.println ("this  ->b= " +b);
         System.out.println ("main()->a= " +a);
       }
    }).show();      // 產生匿名類別物件後即呼叫其 show() 方法
  }
}
//run:
//匿名類別:
//this  ->b= 10000
//main()->a= 10
例3,一樣有宣告參考名稱bird,匿名類別也重新定義speak(),並且直接在匿名類別呼叫speak(),但這是有用到繼承的概念。
package anonymous1;
abstract class Animal {
    abstract Animal speak();
}
class Cat extends Animal {
    public Animal speak() {
        System.out.println("喵喵!");
        return this;
    }
}
class Dog extends Animal {
    public Animal speak() {
        System.out.println("汪汪!");
        return this;
    }
}
public class Anonymous1 {
    static class A{
        int i =0;
        public String showMe(){
            return "This is X";
        }
    }
    public static void main(String[] args) {
        Animal dog = new Dog().speak();
        Animal cat = new Cat().speak();
        Animal bird = new Animal() { // 隱式繼承覆蓋的範例
            @Override
            Animal speak() {
                System.out.println("吱吱!");
                return this;
            }
        }.speak();
    }
}
//run:
//汪汪!
//喵喵!
//吱吱!
例4,介面的匿名類別,有宣告一個Pet介面的參考名稱,也重新定義Pet介面的兩個method,並且用參考名稱呼叫這兩個method。
package anonymous1;
interface Pet {
    void skill();
    void move();
}
public class Anonymous1 {
    public static void main(String[] args) {
        Pet p = new Pet(){
            @Override
            public void skill(){
                System.out.println("我會握手 !");
            }
            @Override
            public void move(){
                System.out.println("我會跑步 !");
            }
        };
        p.skill();
        p.move();
    }
}
//run:
//我會握手 !
//我會跑步 !
例5,也是介面匿名類別範例,跟例4很像,重新定義showMe(),用參考名稱呼叫method。
package anonymous1;
interface X{
    public void showMe();
}
public class Anonymous1 {
    public static void main(String[] args) {
        X x = new X(){       //匿名類別實作X介面
            @Override
            public void showMe(){
                System.out.println("This is Show me!!");
            }
        };
        x.showMe();
    }
}
//run:
//This is Show me!!

這個就比較複雜了,有興趣再慢慢研究。
package anonymous1;
interface A{// 定義介面A
    public void printInfo() ;// 定義抽象方法
}
class X {//定義X類別
    public void fun1(){//定義fun()方法
        this.fun2(new A(){//匿名內部類別
            public void printInfo(){//實現介面中的抽象方法
                System.out.println("Hello World!!!") ;
            }
        });
    }
    public void fun2(A a){//接收介面實例
        a.printInfo();//呼叫介面方法
    }
}
public class Anonymous1 {
    public static void main(String[] args) {
        new X().fun1() ;//產生實體X類別物件並呼叫fun1()方法
    }
}
//run:
//Hello World!!!
結論:匿名類別通常適用在程式不會重複執行,只會做一次,而它不用再做一個類別,可直接在主程式定義一個匿名類別和method,直接使用,簡單說它和一般類別一樣,只是它沒名字。常見的如new Thread(new Runnable(){...}).start() ,寫Android 的 Button。

還有如果匿名類別要存取區域變數,那個區域變數必須宣告為final
像例1的 final String ff="final";   和   static class A{.................

https://sites.google.com/site/dychen1127/java-gui-index/anonymous-class
http://openhome.cc/Gossip/Java/AnonymousInnerClass.html
http://ccckmit.wikidot.com/ja:implicitoverride
http://iamready.myweb.hinet.net/Java/InnerClass.htm http://jhengjyun.blogspot.tw/2009/12/java_19.html

沒有留言:

張貼留言