好文值得轉~
我們都知道,非靜態內部類可以訪問外部類的私有成員(包括私有變量和方法),這也正是使用非靜態內部類與普通類的一個重要區別:非靜態內部類是依賴於外部類對象而存在的,這種依賴就包括它要能自由地訪問外部類對象的所有成員(因爲private成員都可以訪問了,其他權限的成員更不在話下。不過一般來說一個內部類只會訪問外部類的部分成員而不是全部)。比如心臟作爲單獨的一個類存在可能沒有太大的意義,它必須依附於具體的Person對象存在纔有意義,而且心臟它要能夠自由地訪問Person對象的一些成員,如血液、營養等。
顯然,外部類對於非靜態內部類而言是完全透明的。但是實際上,外部類與非靜態內部類的另一個特徵雖然不常用,卻也值得注意,那就是非靜態內部類其實跟外部類的其他成員類似,只是它的一個成員而已,因而即使非靜態內部類的修飾符爲private、即使非靜態內部類的構造器修飾符爲private,外部類也可以新建非靜態內部類的對象。如下例所示:
import java.util.*;
class Car
{
private float gasAmount;
private String gasType;
public Car(float gasAmount,String gasType)
{
this.gasAmount=gasAmount;
this.gasType=gasType;
new Engine();
}
private void print(String msg)
{
System.out.println(msg);
}
private class Engine
{
private int rotateSpeed;
private Engine()
{
if(gasType==93#&&gasAmount>0)
{
rotateSpeed=1500;
print(Gas amount is +String.valueOf(gasAmount)+ gallon now.Engine starts successfully);
}
else if(gasType==93#&&gasAmount<=0)
{
rotateSpeed=0;
print(Engine starts failed! Please add fuel first!);
}
else
{
rotateSpeed=0;
print(Gas type is not correct!);
}
}
}
}
public class OuterSample
{
public static void main(String[]args)
{
new Car(2.0f,93#);
new Car(0.0f,93#);
}
}
輸出結果如下圖所示:
顯然,由輸出結果可看出:第一,雖然非靜態內部類的修飾符和構造器均爲private,但是外部類仍然可以創建內部類對象;第二,非靜態內部類可以使用外部類的private成員(如此處的private成員變量gasType及gasAmount);
另一個常常被人忽略的地方是:在外部類的方法中,也可以通過創建非靜態內部類的對象來訪問內部類包括private成員在內的所有成員,不過注意必須是外部類的實例成員才行,而不能在外部類的靜態成員(包括靜態方法和靜態初始化塊)中使用非靜態內部類,原因很簡單:非靜態內部類可看作是外部類的一個實例成員,而靜態成員不能訪問實例成員。如下例所示:
import java.util.*;
class Car
{
private float gasAmount;
private String gasType;
private Engine engine;
public Car(float gasAmount,String gasType)
{
this.gasAmount=gasAmount;
this.gasType=gasType;
engine=new Engine();
}
public void printRotateSpeed()
{
//其實寫成print(Rotate speed is +String.valueOf(new Engine().rotateSpeed));也行,但是不太符合實際,因爲一車對應一引擎
print(Rotate speed is +String.valueOf(engine.rotateSpeed));
}
private void print(String msg)
{
System.out.println(msg);
}
private class Engine
{
private int rotateSpeed;
private Engine()
{
if(gasType==93#&&gasAmount>0)
{
rotateSpeed=1500;
print(Gas amount is +String.valueOf(gasAmount)+ gallon now.Engine starts successfully);
}
else if(gasType==93#&&gasAmount<=0)
{
rotateSpeed=0;
print(Engine starts failed! Please add fuel first!);
}
else
{
rotateSpeed=0;
print(Gas type is not correct!);
}
}
}
}
public class OuterSample
{
public static void main(String[]args)
{
Car car01=new Car(2.0f,93#);
car01.printRotateSpeed();
Car car02=new Car(0.0f,93#);
car02.printRotateSpeed();
}
}
從輸出結果可以看出,在外部類的方法printRotateSpeed()中,通過非靜態內部類的對象來a訪問了其private成員rotateSpeed,這其實跟實際中的情況很像,即發動機從汽車處獲得燃料信息,汽車再從發動機處獲得轉速並顯示在儀表盤上。
綜上,非靜態內部類可自由訪問外部類包括privated成員在內的所有成員,外部類也可通過創建內部類的對象來訪問其包括private成員在內的所有成員,所以它們雖然在類層面不是相互可見的,但是從廣義上來說具有相互可見性,這也是我在題目上打上雙引號的原因。