內部類
什麼是內部類?簡單點就是面向對象程序設計的概念。面向對象程序設計中,是可以在一個類的內部定義另外一個類,這種類統稱爲嵌套類,它有兩種類型,即靜態嵌套類和非靜態嵌套類。靜態嵌套類使用的頻率很少,基本用不到,最重要的還是非靜態嵌套類,也被稱作爲內部類(inner)。內部類是JAVA語言的主要附加部分。內部類幾乎可以處於一個類內部任何位置,可以與實例變量處於同一級,或處於方法之內,甚至是一個表達式的一部分。
如果一個類存在的意義就是爲指定的另一個類,可以把這個類放入另一個類的內部。就是把類定義在類的內部的情況就可以形成內部類的形式。A類中又定義了B類,B類就是內部類。B類可以當做A類的一個成員看待。
內部類我們從外面看是非常容易理解的,無非就是在一個類的內部在定義一個類。
首先來說一下內部類的三種定義形式:
1、在一個類(外部類)中直接 定義的內部類;
2、在一個方法(外部類的方法)中 定義的內部類;
3、匿名內部類。
內部類的特點:
1、 內部類可以直接訪問外部類中的成員,包括私有成員
2、 外部類要訪問內部類的成員,必須要建立內部類的對象
3、 在成員位置的內部類是成員內部類
4、 在局部位置的內部類是局部內部類
成員內部類被private修飾
- 成員內部類也是最普通的內部類,它是外圍類的一個成員,所以他是可以無限制的訪問外圍類的所有 成員屬性和方法,儘管是private的,但是外圍類要訪問內部類的成員屬性和方法則需要通過內部類實例來訪問。
public class InnerClass2 {
public static void main(String[] args) {
//創建內部類對象,並執行show()
/* -- Outer2.Inner2 oi = new Outer2().new Inner2();
* -- 報錯,Inner2已經被private了
*/
//3,測試被private的內部類的資源能否執行!
new Outer2().test();
}
}
class Outer2{
//2,如果想要訪問private的內部類,可以訪問外部類提供的對應方法
public void test() {
//訪問內部類方法
new Inner2().show();
}
//位置在類裏方法外--成員內部類
//1,內部類可以被private修飾,但是外界無法直接創建對象了!
private class Inner2{
public void show() {
System.out.println("Inner2.show()");
}
}
}
被static修飾的內稱爲靜態內部類,不過我們更喜歡稱之爲嵌套內部類。靜態內部類與非靜態內部類之間存在一個最大的區別,我們知道非靜態內部類在編譯完成之後會隱含地保存着一個引用,該引用是指向創建它的外圍內,但是靜態內部類卻沒有。
-
它的創建是不需要依賴於外圍類的。
-
它不能使用任何外圍類的非static成員變量和方法。
public class InnerClass3 {
public static void main(String[] args) {
// 創建內部類對象測試show()
/* -- Outer3.Inner3 oi = new Outer3().new Inner3();
* -- 報錯,原因是Inner3是靜態的內部類
*/
Outer3.Inner3 oi = new Outer3.Inner3();//Outer3.Inner3通過類名.調用類中的靜態資源
oi.show();
Outer3.Inner3.show2();//調用靜態內部類裏的靜態方法
}
}
class Outer3{
//1,內部類被static修飾--隨着類的加載而加載,會造成內存資源浪費,並不常用!
static class Inner3{
public void show() {
System.out.println("Inner3.show()");
}
static public void show2() {
System.out.println("Inner3.show2()");
}
}
}
局部內部類:有這樣一種內部類,它是嵌套在方法和作用於內的,對於這個類的使用主要是應用與解決比較複雜的問題,想創建一個類來輔助我們的解決方案,到那時又不希望這個類是公共可用的,所以就產生了局部內部類,局部內部類和成員內部類一樣被編譯,只是它的作用域發生了改變,它只能在該方法和屬性中被使用,出了該方法和屬性就會失效。
匿名內部類屬於局部內部類,並且是沒有名字的內部類。
public class InnerClass5 {
public static void main(String[] args) {
new Hello() {// 匿名對象,本身接口不能new,這裏new Hello()匿名對象,就相當於Hello接口的實現類
// 匿名內部類
@Override
public void save() {
System.out.println("save()..");
}
@Override
public void update() {
System.out.println("update()..");
}
}.update();// 觸發指定的方法
new Hello2() {//抽象類的匿名內部類
@Override
public void show() { }
}.show();
new Animal() {//普通類的匿名內部類
@Override
public void eat() { }
};
}
}
//創建匿名對象+匿名內部類測試
class Animal{
public void eat() {}
}
abstract class Hello2 {
abstract public void show();
public void delete() { }
}
// 定義接口
interface Hello {
void save();
void update();
}
觀察上面的代碼,我們看清幾個地方:
-- 匿名內部類是沒有訪問修飾符的。
-- new 匿名內部類,這個類首先是要存在的。如果我們將那個InnerClass接口註釋掉,就會出現編譯出錯。
-- 匿名內部類是沒有構造方法的。因爲它連名字都沒有何來構造方法。
總結:我們爲什麼要使用內部類呢?看過《Think in java》的應該都知道,其中有這樣一句話:“Java在程序設計中使用內部類最吸引人的原因是:每個內部類都能獨立地繼承一個(接口的)實現,所以無論外圍類是否已經繼承了某個(接口的)實現,對於內部類都沒有影響。”甚至可以這樣說,接口只是解決了部分問題,而內部類使得多重繼承的方法方式使解決方案變得更加完整。