內部類是指在一個外部類的內部再定義一個類。內部類做爲外部類的一個成員,而且依附於外部類而存在的。內部類可爲靜態,可用protected和private修飾(而外部類只能使用public和缺省的包訪問權限)。函數
內部類主要有一下幾種:成員內部類、局部內部類、靜態內部類、匿名內部類。學習
(1)、內部類仍然是一個獨立的類,在編譯以後內部類會被編譯成獨立的.class文件,可是前面冠之外部類的類名和$符號 。this
(2)、內部類不能用普通的方式訪問。spa
(3)、內部類聲明成靜態的,就不能隨便的訪問外部類的成員變量了,此時內部類只能訪問外部類的靜態成員變量 。3d
(4)、外部類不能直接訪問內部類的的成員,但能夠經過內部類對象來訪問code
其主要緣由有如下幾點:對象
一、內部類方法能夠訪問該類定義所在的做用域的數據,包括私有的數據blog
二、內部類能夠對同一個包中的其餘類隱藏起來,通常的非內部類,是不容許有 private 與protected權限的,但內部類能夠繼承
三、能夠實現多重繼承接口
四、當想要定義一個回調函數且不想編寫大量代碼時,使用匿名內部類比較便捷
使用內部類最吸引人的緣由是:
每一個內部類都能獨立地繼承自一個(接口的)實現,因此不管外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。你們都知道Java只能繼承一個類,它的多重繼承在咱們沒有學習內部類以前是用接口來實現的。但使用接口有時候有不少不方便的地方。好比咱們實現一個接口就必須實現它裏面的全部方法。而有了內部類就不同了。它可使咱們的類繼承多個具體類或抽象類。
即在一個類中直接定義的內部類,成員內部類與普通類的成員沒什麼區別,能夠與普通成員同樣進行修飾和限制。成員內部類不能含有static的變量和方法。
package com.test; public class Outer { private static int number = 100; private int j = 20; private String name = "Java"; public static void outer_funOne(){ System.out.println("外部類Outer的靜態方法:outer_funOne"); } public void outer_funTwo(){ System.out.println("外部類的普通方法:outer_funTwo"); } //成員內部類,能夠訪問外部類的全部成員 class Demo{ //內部類不容許定義靜態變量 //static int demo_i = 100; int j =50; //內部類和外部類的實例變量能夠共存 //成員內部類中的方法定義 public void demo_funOne(){ //內部類中訪問內部類本身的變量直接用變量名 //也能夠用 this.j System.out.println(j); //內部類中訪問外部類的成員變量語法:外部類類名.this.變量名 System.out.println("內部類訪問外部類變量:"+Outer.this.j); //若是內部類中沒有與外部類中有相同的變量,則能夠直接用變量名使用 System.out.println(name); //內部類調用外部類方法 outer_funOne(); //靜態方法 outer_funTwo(); //非靜態方法 } } public static void outer_funThree(){ //外部類靜態方法訪問成員內部類 // 一、創建外部類對象 Outer out = new Outer(); // 二、根據外部類創建內部類對象 Demo demo = out.new Demo(); // 訪問內部類方法 demo.demo_funOne(); //訪問內部類字段 System.out.println("內部類成員字段:"+demo.j); } public static void main(String[] args) { //調用內部類的方法 // 一、建立外部類對象 Outer out = new Outer(); // 二、經過外部類對象建立內部類對象 Outer.Demo demo = out.new Demo(); // 一、2步簡寫 // Outer.Demo demo1 = new Outer().new Demo(); //方法調用 demo.demo_funOne(); } }
結果:
在方法中定義的內部類稱爲局部內部類。與局部變量相似,局部內部類不能有訪問說明符,由於它不是外圍類的一部分,可是它能夠訪問當前代碼塊內的常量,和此外圍類全部的成員。
須要注意的是:
(1)、局部內部類只能在定義該內部類的方法內實例化,不能夠在此方法外對其實例化。
(2)、局部內部類對象不能使用該內部類所在方法的非final局部變量。
package com.test; public class Outer { private static int number = 100; private int j = 20; private String name = "Java"; //定義外部類方法 public void outer_funOne(int k){ final int number = 100; int j = 50; //方法內部的類(局部內部類) class Demo{ public Demo(int k){ demo_funOne(k); } int number = 300; //能夠定義與外部類同名的變量 // static int j = 10; //不能夠定義靜態變量 //內部類的方法 public void demo_funOne(int k){ System.out.println("內部類方法:demo_funOne"); //訪問外部類的變量,若是沒有與內部類同名的變量,則可直接用變量名 System.out.println(name); //訪問外部類與內部類同名的變量 System.out.println(Outer.this.number); System.out.println("內部類方法傳入的參數是:"+k); } } new Demo(k); } public static void main(String[] args) { //訪問內部類必需要先有外部類對象 Outer out = new Outer(); out.outer_funOne(11); } }
結果:
若是你不須要內部類對象與其外圍類對象之間有聯繫,那你能夠將內部類聲明爲static。這一般稱爲嵌套類(nested class)。想要理解static應用於內部類時的含義,你就必須記住,普通的內部類對象隱含地保存了一個引用,指向建立它的外圍類對象。然而,當內部類是static的時,就不是這樣了。嵌套類意味着:
1. 要建立嵌套類的對象,並不須要其外圍類的對象。
2. 不能從嵌套類的對象中訪問非靜態的外圍類對象。
package com.test; public class Outer { private static int number = 100; private int j = 20; private String name = "Java"; public static void outer_funOne(){ System.out.println("外部類靜態方法:outer_funOne"); } public void outer_funTwo(){ } //靜態內部類能夠用public、protected、private修飾 //靜態內部類能夠定義靜態類或非靜態內部類 private static class Demo{ static int j = 100; String name = "C#"; //靜態內部類裏的靜態方法 static void demo_funOne(){ //靜態內部類只能訪問外部類的靜態成員(靜態變量、靜態方法) System.out.println("靜態內部類訪問外部類靜態變量:"+number); outer_funOne();//訪問外部類靜態方法 } //靜態內部類非靜態方法 void demo_funTwo(){ } } public void outer_funThree(){ //外部類訪問內部類靜態成員:內部類.靜態成員 System.out.println(Demo.j); //訪問靜態方法 Demo.demo_funOne(); //訪問靜態內部類的非靜態成員,實例化內部類便可 Demo demo = new Demo(); //訪問非靜態變量 System.out.println(demo.name); //訪問非靜態方法 demo.demo_funTwo(); } public static void main(String[] args) { new Outer().outer_funThree(); } }
結果:
一、只用到類的一個實例。
二、類在定義後立刻用到。
三、類很是小(SUN推薦是在4行代碼如下)
四、給類命名並不會致使你的代碼更容易被理解。
代碼。。。。。。。。