java內部類

Java內部類和匿名內部類的用法

   

1、內部類: 

       ### (1)內部類的同名方法
        內部類能夠調用外部類的方法,若是內部類有同名方法必須使用"OuterClass.this.MethodName()"格式調用(其中OuterClass與MethodName換成實際外部類名及其方法;this爲關鍵字,表示對外部類的引用);若內部類無同名方法能夠直接調用外部類的方法。
        但外圍類沒法直接調用內部類的private方法,外部類一樣沒法直接調用其它類的private方法。注意:內部類直接使用外部類的方法與該方法的權限與是否static無關,它取決於內部類是否有同名方法。java

package innerclass;
public class OuterClass {
private void outerMethod() {
    System.out.println("It's Method of OuterClass");
}
public static void main(String[] args) {
    OuterClass t = new OuterClass();
    OuterClass.Innerclass in = t.new Innerclass();
    in.innerMethod();
}

class Innerclass {
    public void innerMethod() {
       OuterClass.this.outerMethod();// 內部類成員方法與外部類成員方法同名時,使用this調用外部類的方法
       outerMethod();// 內部類沒有同名方法時執行外部類的方法
    }
    private void outerMethod() {
        System.out.println("It's Method of Innerclass");
    }
}

}
     輸出結果爲:
It's Method of OuterClass
It's Method of Innerclass
    ###(2)內部類訪問外部類的變量必須聲明爲final
      方法中的局部變量,方法結束後這個變量就要釋放掉,final保證這個變量始終指向一個對象。
   首先,內部類和外部類實際上是處於同一個級別,內部類不會由於定義在方法中就會隨着方法的執行完畢而跟隨者被銷燬。問題就來了,若是外部類的方法中的變量不定義final,那麼當外部類方法執行完畢的時候,這個局部變量確定也就被GC了,然而內部類的某個方法尚未執行完,這個時候他所引用的外部變量已經找不到了。若是定義爲final,java會將這個變量複製一份做爲成員變量內置於內部類中,這樣的話,因爲final所修飾的值始終沒法改變,因此這個變量所指向的內存區域就不會變。
     注意,若使用JDK1.8,方法中內部類的方法是能夠直接訪問外部類的方法的局部變量,而且不須要聲明爲final類型。編程

public class OuterClass {
int num1 = 0;// 成員變量

private void outerMethod() {
    int num2 = 0;// 方法內的局部變量
    class Innerclass_1 {
        public void innerMethod() {
            System.out.println(num1);// 方法中內部類的方法,能夠正常訪問外部類的成員變量
            System.out.println(num2);// JDK1.8之前,方法中內部類的方法,不能直接訪問外部類的方法的局部變量,必須聲明爲final
        }
    }
}

}
      若是使用JDK1.8之前的版本,Eclipse會出現以下錯誤提示:ide

    ###(3)內部類的實例化
     內部類實例化不一樣於普通類,普通類能夠在任意須要的時候實例化,而內部類必須在外層類實例化之後方可實例化,並與外部類創建關係
     所以在外部類中的非static方法中,是能夠實例化內部類對象
private void outerMethod() {
System.out.println("It's Method of OuterClass");
Innerclass in = new Innerclass();//在外部類的outerMethod方法中實例化內部類是能夠啊
}
     但在static方法中,就要注意啦!!!!不能在static方法中直接new內部類,不然出現錯誤:
     No enclosing instance of type OuterClass is accessible. Must qualify the allocation with an enclosing instance of type OuterClass (e.g. x.new A() where x is an instance of OuterClass).
     這是由於靜態方法是在類實例化以前就可使用的,經過類名調用,這時動態內部類都還沒實例化呢,怎麼用,總不能調用一個不存在的東西吧。
     若是想在Static方法中new內部類,能夠把內部類聲明爲Static
public class OuterClass {
private void outerMethod() {
System.out.println("It's Method of OuterClass");
}this

public static void main(String[] args) {
    Innerclass in = new Innerclass();
    in.innerMethod();
}

static class Innerclass {//把內部類聲明爲static
    public void innerMethod() {
        System.out.println("It's Method of innerMethod");

    }
}

}
     固然,通常不使用static的方式,而是推薦這種方法:x.new A() ,其中 x是外部類OuterClass的實例,A是內部類Innerclass.net

package innerclass;
public class OuterClass {
private void outerMethod() {
System.out.println("It's Method of OuterClass");
}
public static void main(String[] args) {
OuterClass.Innerclass in = new OuterClass().new Innerclass();//使用x.new A()的方式
in.innerMethod();
}
class Innerclass {
public void innerMethod() {
System.out.println("It's Method of innerMethod");
}
}
}
     x.new A() ,其中 x是外部類OuterClass的實例,A是類部類Innerclass,固然能夠拆分以下,這樣就顯然很明白啦:
public static void main(String[] args) {
OuterClass out = new OuterClass();//外部實例
OuterClass.Innerclass in = out.new Innerclass();//外部實例.new 外部類
in.innerMethod();
}設計

    ###(4)什麼狀況下使用內部類
     典型的狀況是,內部類繼承自某個類或實現某個接口,內部類的代碼操做建立其的外層類的對象。因此你能夠認爲內部類提供了某種進
入其外層類的窗口。
    使用內部類最吸引人的緣由是:每一個內部類都能獨立地繼承自一個(接口的)實現,因此不管外層類是否已經繼承了某個(接口的)實
現,對於內部類都沒有影響。若是沒有內部類提供的能夠繼承多個具體的或抽象的類的能力,一些設計與編程問題就很難解決。從這個角
度看,內部類使得多重繼承的解決方案變得完整。接口解決了部分問題,而內部類有效地實現了「多重繼承」。
   ###(5)在靜態方法中實例化內部類例子:(內部類放在靜態方法中)code

package javatest2;
    public class JavaTest2 {
public static void main(String[] args) {
    class Boy implements Person {
        public void say() {// 匿名內部類自定義的方法say
            System.out.println("say方法調用");
        }
        @Override
        public void speak() {// 實現接口的的方法speak
            System.out.println("speak方法調用");
        }
    }
    Person per = new Boy();
    per.speak();// 可調用
    per.say();// 不能調用
}
 }
   interface Person {
  public void speak();
  }

       per.speak()可調用,而per.say()不能調用,這時由於per是Person對象,要想調用子類的方法,能夠強制向下轉型爲:((Boy) per).say();或者直接改成Boy per = new Boy();。從中可發現,要想調用內部類的自定義的方法,必須經過內部類的對象來調用。那麼,匿名內部類連名字都沒有,怎麼調用內部類自定義的方法?
###(二)匿名內部類
      匿名內部類也就是沒有名字的內部類正由於沒有名字,因此匿名內部類只能使用一次,它一般用來簡化代碼編寫,但使用匿名內部類還有個前提條件:必須繼承一個父類或實現一個接口,但最多隻能繼承一個父類,或實現一個接口。
關於匿名內部類還有以下兩條規則:
    1)匿名內部類不能是抽象類,由於系統在建立匿名內部類的時候,會當即建立內部類的對象。所以不容許將匿名內部類定義成抽象類。
    2)匿名內部類不等定義構造器(構造方法),由於匿名內部類沒有類名,因此沒法定義構造器,但匿名內部類能夠定義實例初始化塊,
    怎樣判斷一個匿名類的存在啊?看不見名字,感受只是父類new出一個對象而已,沒有匿名類的名字。
先看段僞代碼對象

abstract class Father(){
 ....
 }
 public class Test{
 Father f1 = new Father(){ .... }  //這裏就是有個匿名內部類
  }

   通常來講,new 一個對象時小括號後應該是分號,也就是new出對象該語句就結束了。可是出現匿名內部類就不同,小括號後跟的是大括號,大括號中是該new 出對象的具體的實現方法。由於咱們知道,一個抽象類是不能直接new 的,必須先有實現類了咱們才能new出它的實現類。上面的僞代碼就是表示new 的是Father的實現類,這個實現類是個匿名內部類。
    其實拆分上面的匿名內部類可爲:blog

class SonOne extends Father{
 ...       //這裏的代碼和上面匿名內部類,大括號中的代碼是同樣的
   }
   public class Test{
  Father f1 = new SonOne() ;
}

     先看一個例子,體會一下匿名內部類的用法:繼承

    運行結果:eat something
    能夠看到,咱們直接將抽象類Person中的方法在大括號中實現了,這樣即可以省略一個類的書寫。而且,匿名內部類還能用於接口上

public class JavaTest2 {
 public static void main(String[] args) {
    Person per = new Person() {
        public void say() {// 匿名內部類自定義的方法say
            System.out.println("say方法調用");
        }
        @Override
        public void speak() {// 實現接口的的方法speak
            System.out.println("speak方法調用");
        }
    };
    per.speak();// 可調用
    per.say();// 出錯,不能調用
}
 }

  interface Person {
public void speak();
 }

        這裏per.speak()是能夠正常調用的,但per.say()不能調用,爲何呢?注意Person per = new Person()建立的是Person的對象,而非匿名內部類的對象。其實匿名內部類連名字都沒有,你咋實例對象去調用它的方法呢?但繼承父類的方法和實現的方法是能夠正常調用的,本例子中,匿名內部類實現了接口Person的speak方法,所以能夠藉助Person的對象去調用。
        若你確實想調用匿名內部類的自定義的方法say(),固然也有方法:
      (1)相似於speak方法的使用,先在Person接口中聲明say()方法,再在匿名內部類中覆寫此方法。
      (2)其實匿名內部類中隱含一個匿名對象,經過該方法能夠直接調用say()和speak()方法;代碼修改以下:

public class JavaTest2 {
public static void main(String[] args) {
    new Person() {
        public void say() {// 匿名內部類自定義的方法say
            System.out.println("say方法調用");
        }

        @Override
        public void speak() {// 實現接口的的方法speak
            System.out.println("speak方法調用");
        }
    }.say();// 直接調用匿名內部類的方法
}

}
interface Person {
public void speak();
}

原文連接:https://blog.csdn.net/guyuealian/article/details/51981163

相關文章
相關標籤/搜索