java內部類(1):java內部類的建立以及對外提供的訪問方式,匿名內部類詳解
前言
我們在描述事物的時候,事物的內部還有事物,這個內部事物還要訪問外部事物中的內容時。那麼,這個內部事物就可以用內部類來描述。內部類也叫內建類,巢狀類。
正文
一,內部類的形式以及對外訪問的方式
顧名思義,內部類就是一個類巢狀在另一個類中。內部類可以在外部類的成員位置,也可以在外部類的區域性位置,也就是成員函式中。
一般,我們在定義內部類時設定其訪問許可權為私有private,並在外部類中提供訪問它的方法。下面來看例子:
package com.jimmy.basicInnerClass;
class OuterClass{ // 外部類
private int num = 5 ; // 外部類的成員變數
private class InnerClass{ // 私有的內部類,定義在外部類的成員位置
public void innerMethod() { // 內部類的成員方法
System.out.println("你好啊,我是內部類的方法.."+num); // 內部類可直接訪問外部類的成員
}
}
public void outerMethos() { // 外部類方法,例項化內部類物件,並呼叫其方法
OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
innerClass.innerMethod();
}
}
public class InnerClassDemo1 {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.outerMethos(); // 通過外部類方法訪問內部類成員,就像get方法訪問私有成員變數一樣。
}
}
上面程式碼的輸出結果:
你好啊,我是內部類的方法..5
值得注意的是,外部類也是一個完整的類,在編譯的時候也有class檔案生成。上面這個檔案就會產生3個class檔案。內部類的名字比較特別,會標明所屬的外部類名。
OuterClass.class
OuterClass$InnerClass.class
InnerClassDemo1.class
上面的程式碼中,我們直接在外部類的方法中建立了內部類物件,並呼叫了內部類的方法,這樣就顯得有點越俎代庖了。我們想自己拿到內部類的物件來呼叫內部類中的方法。但是,內部類是私有的,我們不能直接new出內部類的物件,雖然可以用“new Outer().new Inner()”來例項化內部類物件,但是卻沒有可用的物件名來接收它(因為內部類對外不可見)。怎麼解決呢?我們知道,內部類也是類,同樣具有類的繼承特性,所以我們將內部類繼承自外部的某個類,或者實現外部的某個介面,就可以通過多型來接收內部類物件了,程式碼如下:
package com.jimmy.basicInnerClass;
interface Inter{ // 外部介面
public void innerMethod();
}
class Outer3{
private int num = 5;
private class Inner implements Inter{ // 內部類實現介面,並實現其中的方法。
@Override
public void innerMethod() {
System.out.println("你好啊,我是內部類的方法...."+num);
}
}
public Inner getInnerObject() { // 外部類函式只返回內部類物件,並不越俎代庖去呼叫方法
return new Inner();
}
}
public class InnerClassDemo5 {
public static void main(String[] args) {
Outer3 outer3 = new Outer3();
Inter innerObject = outer3.getInnerObject(); // 私有的內部類物件可以用多型性來接收
innerObject.innerMethod();
}
}
上述程式碼的輸出結果如下:
你好啊,我是內部類的方法....5
這樣一來,私有化的內部類物件就可以通過多型在外部被持有了,這也符合java中的“面向介面程式設計”的要求。
二,匿名內部類
從上面的程式碼可以看出,內部類在外部類的裡面,並可以實現外部介面,然後實現介面中的方法。有的時候,外部介面中的有些實現只用到一次,也就沒必要特意寫一個類來實現介面,可以使用匿名內部類的形式來實現,匿名內部類在外部類的區域性位置,即方法中。
匿名內部類必須繼承一個父類或者實現一個介面。匿名內部類其實就是一個帶有內容的子類物件,格式為:new 介面/父類(){子類內容}。這個格式比較新穎,一般來說,我們在”new Object();”後會以“;”結束。現在new Object(){}後面跟著的是一對“{}”,表示這是一個子類結構體,介面的實現就在這裡面寫。看個例子:
package com.jimmy.basicInnerClass;
interface InterInner{ // 外部介面以及方法
void innerMethod1();
void innerMethod2();
}
class Outer2{
private int num = 1;
public void outerMethod(){
new InterInner() { // 這就是匿名內部類,大括號裡面是介面的實現
@Override
public void innerMethod1() { // 實現方法1
System.out.println("你好,我是匿名內部類的方法1..."+num);
}
@Override
public void innerMethod2() { // 實現方法2
// TODO Auto-generated method stub
System.out.println("你好,我是匿名內部類的方法2..."+num+1);
}
}.innerMethod1(); // new出物件,就能呼叫函式
}
}
public class InnerClassDemo4 {
public static void main(String[] args) {
Outer2 outer2 = new Outer2();
outer2.outerMethod();
}
}
上面程式碼new出匿名內部類的物件後直接呼叫了實現後的方法。程式碼輸出:
你好,我是匿名內部類的方法1...1
我們也可以提供匿名內部類的物件,並在外部呼叫匿名內部類的方法,程式碼如下:
package com.jimmy.basicInnerClass;
interface InterInner2{ // 外部介面以及方法
void innerMethod1();
void innerMethod2();
}
class Outer4{
private int num = 1;
public InterInner2 outerMethod(){
InterInner2 inner2 = new InterInner2() { // 接收匿名內部類物件,大括號裡面是介面的實現
@Override
public void innerMethod1() { // 實現方法1
System.out.println("你好,我是匿名內部類的方法1..."+num);
}
@Override
public void innerMethod2() { // 實現方法2
// TODO Auto-generated method stub
System.out.println("你好,我是匿名內部類的方法2..."+(num+1));
}
};
return inner2;
}
}
public class InnerClassDemo4_1 {
public static void main(String[] args) {
Outer4 outer4 = new Outer4();
InterInner2 inner2 = outer4.outerMethod();
inner2.innerMethod1();
inner2.innerMethod2();
}
}
程式碼輸出為:
你好,我是匿名內部類的方法1...1
你好,我是匿名內部類的方法2...2
三,匿名內部類的常見用法
匿名內部類只是對介面的一次實現和呼叫,用完就被回收了。其使用可以像上面那樣,將匿名內部類放在外部類的方法中,在外面呼叫外部類的方法,得到內部類物件進而呼叫內部類的方法。如果內部類不需要訪問外部類的成員變數,就可以直接將其放在main方法中。如下示例:
package com.jimmy.niMingInnerClass;
interface movable{
public void run();
}
public class NimingInnerClassDemo1 {
public static void main(String[] args) {
new movable() {
@Override
public void run() {
System.out.println("i am running...");
}
}.run();
}
}
輸出結果:
i am running...
實際中使用匿名內部類有很多,常見的就是建立執行緒時使用匿名內部類,如下示例:
package com.jimmy.niming;
public class NiMingNeibuleiTest {
public static void main(String[] args) {
new Thread(new Runnable() { // 執行緒1
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}
}).start();
new Thread(new Runnable() { // 執行緒2
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}
}).start();
}
}
輸出結果:
2個執行緒交替執行
總結
只學會了內部類的形式和對外呼叫方法,以及匿名內部類如何實現簡化程式碼。並不是很理解內部類的好處,以後程式設計學習過程中慢慢體會。