java中的內部類
一.什么是內部類?
答:內部類( Inner Class )就是定義在另外一個類里面的類。與之對應,包含內部類的類被稱為外部類
二.為什么要使用內部類?
答:1.內部類可以提供更好的封裝,將一個類隱藏在另一個類內,不允許同一個包中其他類訪問這個內部類
2.內部類的方法可以直接訪問外部類的所有數據,包括私有的數據
3.內部類所實現的功能使用外部類同樣可以實現,只是有時使用內部類更方便
三.內部類有幾種?
答:1.成員內部類
2.靜態內部類
3.方法內部類
4.匿名內部類
四.介紹四種內部類
(1)成員內部類:
1.Inner 類定義在 Outer 類的內部,相當于 Outer 類的一個成員變量的位置,Inner 類可以使用任意訪問控制符,如 public 、 protected 、 private 等
2.Inner 類中定義的 test() 方法可以直接訪問 Outer 類中的數據,而不受訪問控制符的影響,如直接訪問 Outer 類中的私有屬性a
3.定義了成員內部類后,必須使用外部類對象來創建內部類對象,而不能直接去 new 一個內部類對象,即:內部類 對象名 = 外部類對象.new 內部類( );
4.編譯之后,會出現兩個.class文件。HelloWorld.class 和 HelloWorld$Inner.class
5.外部類是不能直接使用內部類的成員和方法,可先創建內部類的對象,然后通過內部類的對象來訪問其成員變量和方法。
6.如果外部類和內部類具有相同的成員變量或方法,內部類默認訪問自己的成員變量或方法,如果要訪問外部類的成員變量,可以使用 this 關鍵字
//外部類HelloWorld
public class HelloWorld{
//外部類的私有屬性name
private String name = "study";
//外部類的成員屬性
int age = 20;
//成員內部類Inner
public class Inner {
String name = "學習";
//內部類中的方法
public void show() {
//訪問外部類中的同名變量需要使用this變量去訪問
System.out.println("外部類中的name:" + HelloWorld.this.name);
System.out.println("內部類中的name:" +name);
System.out.println("外部類中的age:" + age);
}
}
//測試成員內部類
public static void main(String[] args) {
//創建外部類的對象
HelloWorld o = new HelloWorld ();
//創建內部類的對象,定義了成員內部類后,必須使用外部類對象來創建內部類對象
Inner inn = o.new Inner();
//調用內部類對象的show方法
inn.show();
}
}
</code></pre>
運行結果:
外部類中的name:study
內部類中的name:學習
外部類中的age:20
(2)靜態內部類
1.靜態內部類不能直接訪問外部類的非靜態成員,但可以通過 new 外部類().成員 的方式訪問
int wo=new HelloWorld().shei;
2.如果外部類的靜態成員與內部類的成員名稱相同,可通過“類名.靜態成員”訪問外部類的靜態成員;如果外部類的靜態成員與內部類的成員名稱不相同,則可通過“成員名”直接調用外部類的靜態成員
3.創建靜態內部類的對象時,不需要外部類的對象,可以直接創建 內部類 對象名= new 內部類();
//外部類
public class HelloWorld {
// 外部類中的靜態變量score
private static int score = 84;
private int shei=1;
// 創建靜態內部類
public static class SInner {
// 內部類中的變量score
int score = 91;
public void show() {
//訪問同名靜態變量類名.靜態變量
System.out.println("訪問外部類中的score:" + HelloWorld.score);
System.out.println("訪問內部類中的score:" + score);
//不能直接訪問非靜態變量
int wo=new HelloWorld().shei;
}
}
// 測試靜態內部類
public static void main(String[] args) {
// 直接創建內部類的對象,不用 外部類對象.new SInner();
SInner si=new SInner();
// 調用show方法
si.show();
}
}
</code></pre>
運行結果:
訪問外部類中的score:84
訪問內部類中的score:91
</code></pre>
(3)方法內部類
1.方法內部類就是內部類定義在外部類的方法中,方法內部類只在該方法的內部可見,即只在該方法內可以使用。
2.由于方法內部類不能在外部類的方法以外的地方使用,因此方法內部類不能使用訪問控制符和 static 修飾符
//外部類
public class HelloWorld {
private String name = "學習";
// 外部類中的show方法
public void show() {
// 定義方法內部類
class MInnder {
int score = 83;
public int getScore() {
return score + 10;
}
}
// 創建方法內部類的對象
MInner inner=new MInner();
// 調用內部類的方法
int newScore=inner.getScore();
System.out.println("姓名:" + name + "\n加分后的成績:" + newScore);
}
// 測試方法內部類
public static void main(String[] args) {
// 創建外部類的對象
HelloWorld mo=new HelloWorld();
// 調用外部類的方法
mo.show();
}
}
</code></pre>
運行結果:
姓名:學習
加分后的成績:93
(4)匿名內部類
1.匿名內部類也就是沒有名字的內部類
2.正因為沒有名字,所以匿名內部類只能使用一次,它通常用來簡化代碼編寫
3.但使用匿名內部類還有個前提條件:必須繼承一個父類或實現一個接口
實例1:不使用匿名內部類來實現抽象方法
//抽象類
abstract class Person {
public abstract void eat();
}
//繼承并實現抽象方法eat
class Child extends Person {
public void eat() {
System.out.println("eat something");
}
}
public class Demo {
public static void main(String[] args) {
Person p = new Child();
p.eat();
}
}
</code></pre>
運行結果:eat something
可以看到,我們用Child繼承了Person類,然后實現了Child的一個實例,將其向上轉型為Person類的引用
但是,如果此處的Child類只使用一次,那么將其編寫為獨立的一個類豈不是很麻煩?
這個時候就引入了匿名內部類
實例2:匿名內部類的基本實現
abstract class Person {
public abstract void eat();
}
public class Demo {
public static void main(String[] args) {
//抽象類的方法直接在大括號中實現
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
</code></pre>
運行結果:eat something
可以看到,我們直接將抽象類Person中的方法在大括號中實現了
這樣便可以省略一個類的書寫
并且,匿名內部類還能用于接口上
實例3:在接口上使用匿名內部類
interface Person {
public void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
</code></pre>
運行結果:eat something
由上面的例子可以看出,只要一個類是抽象的或是一個接口,那么其子類中的方法都可以使用匿名內部類來實現
最常用的情況就是在多線程的實現上,因為要實現多線程必須繼承Thread類或是繼承Runnable接口
實例4:Thread類的匿名內部類實現
public class Demo {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
t.start();
}
}
運行結果:1 2 3 4 5
實例5:Runnable接口的匿名內部類實現
public class Demo {
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
}
};
Thread t = new Thread(r);
t.start();
}
}
運行結果:1 2 3 4 5
來自:http://www.cnblogs.com/jijiji/p/5934080.html