java四種內部類詳解
一般來說,有4中內部類:常規內部類、靜態內部類、區域性內部類、匿名內部類。
一.常規內部類:常規內部類沒有用static修飾且定義在在外部類類體中。
1.常規內部類中的方法可以直接使用外部類的例項變數和例項方法。
2.在常規內部類中可以直接用內部類建立物件
3.程式碼如下:
public class MyOuter {
private int x = 100;
// 建立內部類
class MyInner {
private String y = "Hello!";
public void innerMethod() {
System.out.println("內部類中 String =" + y);
System.out.println("外部類中的x =" + x);// 直接訪問外部類中的例項變數x
outerMethod();
System.out.println("x is" + MyOuter.this.x);
}
}
public void outerMethod() {
x++;
}
public void makeInner() {
//在外部類方法中建立內部類例項
MyInner in = new MyInner();
}
/**
* @param args
*/
public static void main(String[] args) {
MyOuter mo = new MyOuter();
// 使用外部類構造方法建立mo物件
MyOuter.MyInner inner = mo.new MyInner();//常規內部類需要通過外部類的例項才能建立物件,與例項變數需要通過物件來訪問相似
// 建立inner物件
inner.innerMethod();
// TODO Auto-generated method stub
}
}
4.執行結果:
內部類中 String =Hello!
外部類中的x =100
x is101
二.靜態內部類:與類的其他成員相似,可以用static修飾內部類,這樣的類稱為靜態內部類。靜態內部類與靜態內部方法相似,只能訪問外部類的static成員,不能直接訪問外部類的例項變數,與例項方法,只有通過物件引用才能訪問。
3.由於static內部類不具有任何對外部類例項的引用,因此static內部類中不能使用this關鍵字來訪問外部類中的例項成員,但是可以訪問外部類中的static成員。這與一般類的static方法想通
4.例項程式碼:
package com.m.ou;
public class MyOuter {
public static int x=100;
public static class MyInner{
private String y="Hello!";
public void innerMethod(){
System.out.println("x="+x);
System.out.println("y="+y);
}
}
/**
* @param args
*/
public static void main(String[] args) {
MyOuter.MyInner si=new MyOuter.MyInner();//靜態內部類不通過外部例項就可以建立物件;與類變數可以通過類名訪問相似
si.innerMethod();
// TODO Auto-generated method stub
}
}
4.執行結果:
x=100
y=Hello!
三.區域性內部類:在方法體或語句塊(包括方法、構造方法、區域性塊或靜態初始化塊)內部定義的類成為區域性內部類。
區域性內部類不能加任何訪問修飾符,因為它只對區域性塊有效。
1.區域性內部類只在方法體中有效,就想定義的區域性變數一樣,在定義的方法體外不能建立區域性內部類的物件
2.在方法內部定義類時,應注意以下問題:
1.方法定義區域性內部類同方法定義區域性變數一樣,不能使用private、protected、public等訪問修飾說明符修飾,也不能使用static修飾,但可以使用final和 abstract修飾
2.方法中的內部類可以訪問外部類成員。對於方法的引數和區域性變數,必須有final修飾才可以訪問。
3.static方法中定義的內部類可以訪問外部類定義的static成員
3.程式程式碼:
public class Jubu {
private int size=5,y=7;
public Object makeInner(int localVar){
final int finalLocalVar=localVar;
//建立內部類,該類只在makeInner()方法有效,就像區域性變數一樣。在方法體外部不能建立MyInner類的物件
class MyInner{
int y=4;
public String toString(){
return "OuterSize:"+size+
"\nfinalLocalVar"+" "+"this.y="+this.y;
}
}
return new MyInner();
}
}
class Main{ /**
* @param args
*/
public static void main(String[] args) {
Object obj=new Jubu().makeInner(47);//建立Jubu物件obj,並呼叫它的makeInner()方法,該方法返回一個
//該方法返回一個MyInner型別的的物件obj,然後呼叫其同toString方法。
System.out.println(obj.toString());
// TODO Auto-generated method stub
}
}
4.執行結果:
OuterSize:5
finalLocalVar this.y=4
四.匿名內部類:定義類的最終目的是建立一個類的例項,但是如果某個類的例項只是用一次,則可以將類的定義與類的建立,放到與一起完成,或者說在定義類的同時就建立一個類
以這種方法定義的沒有名字的類成為匿名內部類。
宣告和構造匿名內部類的一般格式如下:
new ClassOrInterfaceName(){
/*類體*/ }
1.匿名內部類可以繼承一個類或實現一個介面,這裡的ClassOrInterfaceName是匿名內部類所繼承的類名或實現的介面名。但匿名內部類不能同時實現一個介面和繼承一個類,也不能實現多個介面。如果實現了一個介面,該類是Object類的直接子類,匿名類繼承一個類或實現一個介面,不需要extends和implements關鍵字。
2.由於匿名內部類沒有名稱,所以類體中不能定義構造方法,由於不知道類名也不能使用關鍵字來建立該類的例項。實際上匿名內部類的定義、構造、和第一次使用都發生在同樣一個地方。此外,上式是一個表示式,返回的是一個物件的引用,所以可以直接使用或將其複製給一個物件變數。例:
TypeName obj=new Name(){
/*此處為類體*/
}
同樣,也可以將構造的物件作為呼叫的引數。例:
someMethod(new Name(){
/*此處為類體*/ });
3.程式程式碼:
public class NiMing {
private int size=5;
public Object makeInner(int localVar){
final int finalLocalVar=localVar;
return new Object(){
//使用匿名內部類
public String toString(){
return "OuterSize="+size+"\nfinalLocalVar="+finalLocalVar;
}
};
}
/**
* @param args
*/
public static void main(String args[])
{
Object obj=new NiMing().makeInner(47);
System.out.println(obj.toString());
}
}
4.程式執行結果:
OuterSize=5
finalLocalVar=47