class A{
class B{}
}
這樣的類被稱為內(nèi)部類,又被稱為內(nèi)隱類. 從簡單到深入一步一步的分析內(nèi)部類的特點(diǎn)。
class OuterClass{
static class A{//靜態(tài)內(nèi)部類
public A( ){
System.out.println("Test$A !");
}
}
class B{//非靜態(tài)內(nèi)部類
public B(){
System.out.println("Test$B !");
}
}
public void disp( )
{
final int a=10; int b;
class C //成員函數(shù)中的局部內(nèi)部類
{ 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(); //建立靜態(tài)內(nèi)部類對(duì)象
B b=new OuterClass( ).new B();
//建立非靜態(tài)內(nèi)部類的對(duì)象
//注意這個(gè)OuterClass().new B();相當(dāng)于生成一個(gè)外部類的對(duì)象,然后在利用外部類對(duì)象生成內(nèi)部類對(duì)象
OuterClass t=new OuterClass( );
t.disp( );
//通過外部對(duì)象調(diào)用一個(gè)對(duì)象方法的形式,新建立了對(duì)象C.
}
}
注意在上面的b在運(yùn)行時(shí)會(huì)為0,因?yàn)槭穷悓傩?
class OuterClass
{
static class A { } //靜態(tài)內(nèi)部類
class B { } //非靜態(tài)內(nèi)部類
public void disp( )
{
class C{ } //局部內(nèi)部類
}
}
編譯后的將產(chǎn)生下面的一些類文件:
OuterClass.class
OuterClass$A.class
OutClass$B.class
OuterClass$1$C.class
記住以下幾句話:
1.一個(gè)內(nèi)部類的對(duì)象能夠訪問創(chuàng)建它的外部類對(duì)象的所有屬性及方法(包括私有部分)。
//可以閉上眼睛,把這個(gè)內(nèi)部類等同于一個(gè)類的一個(gè)方法,當(dāng)然就可以訪問這個(gè)外部類的
//所有方法和屬性,私有方法和屬性是屬于外部類的,當(dāng)然也就等同于內(nèi)部類的.
2.對(duì)于同一個(gè)包中的其它類來說,內(nèi)部類能夠隱藏起來。(將內(nèi)部類用private修飾即可)
//只有在內(nèi)部類中,才能定義一個(gè)為private類型的class,因?yàn)檫@時(shí)編譯器已經(jīng)把這個(gè)類看作這個(gè)類的成員了,但是在一般使用時(shí),就是所謂的”頂級(jí)類時(shí)”,不能使用private,只能是public 或者是friendly. 如果要是想保證一個(gè)類不產(chǎn)生任何的對(duì)象,請(qǐng)?jiān)跇?gòu)造函數(shù)中,把構(gòu)造函數(shù)聲明成private.
3. 內(nèi)部類可定義在方法中,稱為局部內(nèi)部類,但它只能使用方法中的final常量。
// 定義在一個(gè)方法內(nèi)的類,又被成為局部內(nèi)部類,這個(gè)類只能使用在方法中的final常量,注意,這個(gè)常量是在一個(gè)方法中的,那么能否使用一個(gè)類中的常量呢?
當(dāng)然是可以的,因?yàn)轭愔械某A吭谠谝粋€(gè)方法中是可見的.
//
如果把一個(gè)類寫在了一個(gè)if中,比如這樣:
class A{
int a = 10;
if(a!=10){
class B{
B(){
System.out.println(a);
}
}
}
}
在編譯后會(huì)有幾個(gè)錯(cuò)誤呢?
首先那個(gè)a沒有被定義為final,你又一次上了圈套. 類B同樣會(huì)被生成出來,只是離開了if域就失效了.
4.內(nèi)部類可以被定義為抽象類
// abstract 類同樣可以在內(nèi)部類中
5. 非靜態(tài)內(nèi)部類不能聲明本類的static成員
//只有一個(gè)靜態(tài)的內(nèi)部類,才可以聲明一個(gè)static成員,
class A{
static class B{
//如果這里不是一個(gè)static類,是不可以被聲明這個(gè)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();
}
}
使用內(nèi)部類可以非常方便的編寫事件驅(qū)動(dòng)程序
這個(gè)在寫事件驅(qū)動(dòng)時(shí),會(huì)有很好的解釋.
匿名內(nèi)部類
在某些情況下,我們只需要內(nèi)部類的一個(gè)對(duì)象,那么我們就沒有必要給內(nèi)部類命名,沒有名字的內(nèi)部類我們稱為匿名內(nèi)部類
public class A extends Applet
{ public void init( )
{ addMouseListener( new B( ) );
}
class B extends MouseAdapter
{ public void mousePressed(MouseEvent me)
{ showStatus("Mouse Pressed."); }
}
}
用匿名內(nèi)隱類修改:
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"); } } );
}
}
下面是一個(gè)think in java里的例子
public class Pr{
public Concents cont(){
return new Concents(){
private int i= 11;
public int value (){return i;}
};//這里是有一個(gè)分號(hào)
}
}
這個(gè)Contents是通過默認(rèn)的構(gòu)造函數(shù)產(chǎn)生的,匿名類的產(chǎn)生也就是一個(gè)新類向上轉(zhuǎn)型到父類的過程.
那么如果一個(gè)父類沒有一個(gè)默認(rèn)的構(gòu)造函數(shù),應(yīng)該什么辦呢? 那就只有調(diào)用一個(gè)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);
}
}
如果在匿名內(nèi)部類中用到了外部對(duì)象 , 就必須保證這個(gè)外部對(duì)象是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);
}
}