Java內部類
(嵌套的)內部類:
- 成員類
- 局部類(方法或者代碼塊)
- 匿名類
內部類的權限
- 外部類所有的成員(比如私有的)都有權限訪問內部類 [通常沒有任何的權限
修飾,但是如果對內部類是隱藏的,可以通過Outer.this.outerVar來引用]
- 靜態內部類不可以引用外部類的實例變量(沒有實例),但是可以引用外部類
的靜態變量(我想,引用靜態的類也是允許的)
- 局部內部類不能引用非最終(final)的局部變量和方法參數,與類一級的內部類不同的是,
局部類是按次序執行的,所以你不能在定義之前創建一個類的實例
實例化:
- 內部類的引用:Outer.Inner i = new Outer().new Inner();
即使在外部類的范圍內,你也需要一個外部類的實例
- 靜態內部類的引用:Outer.Nested nested = new Outer.Nested();
????????????
關鍵字static使一個頂層的構造(類,方法或者成員變量)不屬于他的外部類實例
- 內部類不能有靜態成員
- 方法不能有靜態成員
本文將詳細的解釋內部類,希望和大家交流.
簡單的內部類定義形如這樣:
class A{
class B{}
}這樣的類被稱為內部類,又 被稱為內隱類.
從簡單到深入一步一步的分析內部類的特點.
class OuterClass
{ static class A //靜態內部類
{ public A( )
{ System.out.println("Test$A !"); } }
class B //非靜態內部類
{ public B( )
{ System.out.println("Test$B !"); } }
public void disp( )
{
final int a=10; int b;
class C //成員函數中的局部內部類
{ public C( )
{ System.out.println(“in class C a="+a);
//System.out.println(b);
}
}
C c=new C( );
}
public class Test extends OuterClass
{
public static void main(String args[])
{ OuterClass.A a=new OuterClass.A( );
//建立靜態內部類對象
B b=new OuterClass( ).new B( );
//建立非靜態內部類的對象
//注意這個OuterClass().new B();相當于生成一個外部類的對象,然后在利用外部類對象生成內部類對象
OuterClass t=new OuterClass( );
t.disp( );
//通過外部對象調用一個對象方法的形式,新建立了對象C.
}
}
注意在上面的b在運行時會為0,因為是類屬性.
class OuterClass
{
static class A { } //靜態內部類
class B { } //非靜態內部類
public void disp( )
{
class C{ } //局部內部類
}
}
編譯后的結果:
OuterClass.class
OuterClass$A.class
OutClass$B.class
OuterClass$1$C.class
記住以下幾句話:
1,一個內部類的對象能夠訪問創建它的外部類對象的所有屬性及方法(包括私有部分)。
//可以閉上眼鏡,把這個內部類等同于一個類的一個方法,當然就可以訪問這個外部類的
//所有方法和屬性,私有方法和屬性是屬于外部類的,當然也就等同于內部類的.
2,對于同一個包中的其它類來說,內部類能夠隱藏起來。(將內部類用private修飾即可)
//只有在內部類中,才能定義一個為private類型的class,因為這時編譯器已經把這個類看作這個類的成員了,但是在一般使用時,就是所謂的”頂級類時”,不能使用private,只能是public 或者是friendly.
如果要是想保證一個類不產生任何的對象,請在構造函數中,把構造函數聲明成private.
3, 內部類可定義在方法中,稱為局部內部類,但它只能使用方法中的final常量。
// 定義在一個方法內的類,又被成為局部內部類,這個類只能使用在方法中的final常量,注意,這個常量是在一個方法中的,那么能否使用一個類中的常量呢?
當然是可以的,因為類中的常量在在一個方法中是可見的.
//
如果把一個類寫在了一個if中,比如這樣:
class A{
int a = 10;
if(a!=10){
class B{
B(){
System.out.println(a);
}
}
}
}
在編譯后會有幾個錯誤呢?
首先那個a沒有被定義為final,你有一次上了圈套.
類B同樣會被生成出來,只是離開了if域就失效了.
4,內部類可以被定義為抽象類
// abstract 類同樣可以在內部類中
5, 非靜態內部類不能聲明本類的static成員
//只有一個靜態的內部類,才可以聲明一個static成員,
class A{
static class B{
//如果這里不是一個static類,是不可以被聲明這個gg方法的.
static void gg(){
int a = 100;
System.out.println(a);
}
}
}
class aa{
public static void main(String args[]){
A.B hh = new A.B();
hh.gg();
}
}
使用內部類可以非常方便的編寫事件驅動程序
這個在寫事件驅動時,會有很好的解釋.
匿名內部類
在某些情況下,我們只需要內部類的一個對象,那么我們就沒有必要給內部類命名,沒有名字的內部類我們稱為匿名內部類
public class A extends Applet
{ public void init( )
{ addMouseListener( new B( ) );
}
class B extends MouseAdapter
{ public void mousePressed(MouseEvent me)
{ showStatus("Mouse Pressed."); }
}
}
用匿名內隱類修改:
import java.applet.*;
import java.awt.event.*;
import java.awt.*;
public class AnonymousInnerClassDemo extends Applet
{ public void init( )
{ addMouseListener( new MouseAdapter( )
{ public void mousePressed(MouseEvent me)
{ showStatus("Mouse Pressed"); } } );
}
}
下面是一個think in java里的例子
public class Pr{
public Concents cont(){
return new Concents(){
private int i= 11;
public int value (){return i;}
};//這里是有一個逗號
}
}
這個Contents是通過默認的構造函數產生的,匿名類的產生也就是一個新類向上轉型到父類的過程.
那么如果一個父類沒有一個默認的構造函數,應該什么辦呢?
那就只有調用一個super()了.
class noname{
Warpping wrap(int x){
return new Warpping(x){
public int value(){
return super.value()*47;
}
};
}
public static void main(String s[]){
noname p = new noname();
Warpping w = p.wrap(10);
}
}
如果在匿名內部類中用到了外部對象
就必須保證這個外部對象是final的
public class PP{
public DD dest(final String dest, final float price){
return new DD(){
private int cost;
{
cost = Math.round(price);
if(cost>100)
System.out.println("Over budget");
}
};
}
publc static void main(String []arg){
PP h = new PP();
DD d = h.dest("haha",11.111);
}
}