能夠將一個類定義在另外一個類裏面或者一個方法裏面,這樣的類稱爲內部類。java
普遍意義上的內部類通常來講包括這四種:函數
成員內部類是最普通的內部類,它的定義爲位於另外一個類的內部,形以下面的形式:測試
public class testDemo { public static void main(String[] args ) { Outer t = new Outer(); Outer.Inner in = t.new Inner(); // 必須先有外部類對象,才能建立內部類 t.fun(); in.print(); } } class Outer { //外部類 private String msg = "hello world"; public void fun(){ Inner in = new Inner(); System.out.println(in.info); //外部類直接訪問內部類的私有屬性 } class Inner{ //定義了一個成員內部類 private String info = "世界,你好!"; public void print(){ System.out.println(msg); //內部類直接訪問外部類的private屬性 } } }
成員內部類能夠無條件訪問外部類的全部屬性和方法(包括private成員和靜態成員)。外部類也能夠直接訪問內部類的全部屬性和方法。this
成員內部類是依附外部類而存在的,也就是說,若是要建立成員內部類的對象,前提是必須存在一個外部類的對象設計
在外部類中若是要訪問成員內部類的成員,必須先建立一個成員內部類的對象,再經過指向這個對象的引用來訪問。code
不過要注意的是,當成員內部類擁有和外部類同名的成員變量或者方法時,會發生隱藏現象,即默認狀況下訪問的是成員內部類的成員。若是要訪問外部類的同名成員,須要如下面的形式進行訪問:對象
外部類.this.成員變量 外部類.this.成員方法
局部內部類是定義在一個方法或者一個做用域裏面的類,它和成員內部類的區別在於局部內部類的做用域僅限於方法內或者該做用域內。繼承
public class testDemo { public static void main(String[] args ) { new Outer().fun(); } } class Outer { //外部類 private String msg = "hello world"; public void fun(){ class Inner{ //在方法中定義了一個局部內部類 public void print(){ System.out.println(Outer.this.msg); //直接訪問外部類的private屬性 } } new Inner().print(); } }
注意:局部內部類就像是方法裏面的一個局部變量同樣。接口
在jdk1.7或以前的版本,若是局部內部類要訪問方法中定義的參數、局部變量,那麼參數和變量前必定要加上"final"修飾符。jdk1.8以及更新的版本則沒有這個限制。作用域
public class testDemo { public static void main(String[] args ) { new Outer().fun(100); } } class Outer { //外部類 private String msg = "hello world"; public void fun(final int num){ final double score = 99.9; class Inner{ //在方法中定義了一個局部內部類 public void print(){ System.out.println("屬性:"+Outer.this.msg); //直接訪問外部類的private屬性 System.out.println("方法參數"+ num); System.out.println("方法局部變量"+ score); } } new Inner().print(); } }
使用static修飾的成員內部類叫靜態內部類。靜態內部類是不須要依賴於外部類的,這點和類的靜態成員屬性有點相似,而且它不能訪問外部類的非static成員變量或者方法。
public class testDemo { public static void main(String[] args ) { Outer.Inner in = new Outer.Inner(); //靜態內部類可使用"外部類.內部類"的方式使用 in.print(); } } class Outer { //外部類 static class Inner{ //定義了一個靜態內部類 private String info = "世界,你好!"; public void print(){ System.out.println(info); } } }
當某個子類只使用惟一一次的時候,沒有必要單獨定義出來,可使用匿名內部類的方法簡化代碼。
匿名內部類就是沒有名字的局部內部類。建立格式以下:
new 父類構造器(參數列表)| 要實現的接口 () { //匿名內部類的類體部分 //.... }
匿名內部類是在抽象類和接口的基礎上發展而來的,其最大的好處是幫助減小了類的定義。
在使用匿名內部類的過程當中,咱們須要注意以下幾點:
示例:
//接口 interface Inner { public String say(); } //抽象類 abstract class Inner1 implements Inner{ } //普通類 class Inner2 implements Inner{ public String say(){ return "this is Inner2"; } } class Outer { public void method1(Inner inner) { System.out.println(inner.say()); } } public class testDemo { public static void main(String[] args) { Outer outer = new Outer(); // 測試1,Inner爲接口 outer.method1(new Inner() { String s1 = "this is s1 in Inner"; public String say() { // 外部類和匿名函數類中有同名變量s1 return s1; } }); // 測試2,Inner1爲抽象類 outer.method1(new Inner1() { String s2 = "this is s2 in Inner1"; public String say() { // 外部類和匿名函數類中有同名變量s2 return s2; } }); //測試3, Inner2爲普通類 outer.method1(new Inner2() { public String say() { return "this is inner2 overrite"; } }); } } 輸出結果: this is s1 in Inner this is s2 in Inner1 this is inner2 overrite
爲何要使用內部類?在《Think in java》中有這樣一句話:使用內部類最吸引人的緣由是:每一個內部類都能獨立地繼承一個(接口的)實現,因此不管外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。
在咱們程序設計中有時候會存在一些使用接口很難解決的問題,這個時候咱們能夠利用內部類提供的、能夠繼承多個具體的或者抽象的類的能力來解決這些程序設計問題。能夠這樣說,接口只是解決了部分問題,而內部類使得多重繼承的解決方案變得更加完整。內部類最大的優勢就在於它可以很是好的解決多重繼承的問題.
內部類還可以爲咱們帶來以下特性: