【IT168 文檔】有時候開發時為了方便,在代碼中使用了不少嵌套類(nested class),但是使用過程中如果不了解嵌套類的特性,可能會造成意想不到的情況。
Java對象想要通過網絡傳輸,必須實現序列化接口,於是我們在Service中定義了了一個實現了序列化接口的內部類,然後調用遠程接口將其傳輸到網絡上。
一運行報異常:不能將沒有實現序列化接口的Object序列化。
怎麼回事,這是一個很簡單的內部類,的確已經實現了序列化接口了,其定義的成員都是可序列化的String類型;將其換成普通類沒有問題。難道不能使用序列化的內部類?
其實我們使用的內部類是嵌套類(nested class)的一種,而nested class 共有四種:
static nested class 靜態嵌套類inner class 內部類(非靜態)local class 本地類(定義在方法內部)anonymous class 匿名類靜態嵌套類的行為更接近普通的類,另外三個是真正的內部類。區別在於作用域的不同。
以下是對他們的性質描述:
以下還有一段程序說明它們的區別和使用方式:
Java代碼
/**
*
* 普通內部類持有對外部類的一個引用, 靜態內部類卻沒有
*
* @author howard
*/
public class OutterClass {
/*
* this is static nested class
*/
private static class StaticNestedClass {
private void yell() {
System.out.println(this.toString());
// OutterClass.this.yell();//靜態內部類實例沒有外部類實例的引用
}
}
/*
* this is inner class
*/
private class InnerClass {
private void yell() {
System.out.println(this.toString());
OutterClass.this.yell();//內部類實例顯式使用外部類實例的方式
}
}
private void yell() {
System.out.println( this.toString());
}
private void run() {
/*
* this is local class
*/
class LocalClass {
public void yell(){
System.out.println(this.toString());
}
}
/*
* this is anonymous class
*/
new Object() {
public void yell(){
System.out.println(this.toString());
}
}.yell();
LocalClass lc=new LocalClass();
InnerClass ic = new InnerClass();
StaticNestedClass sc=new StaticNestedClass();
lc.yell();
ic.yell();
sc.yell();
}
public static void main(String[] args) {
OutterClass oc = new OutterClass();
oc.run();
}
}
仔細分析如上代碼,可以得出一個結論,所有的內部類,Local內部類,匿名內部類都可以直接訪問外面的封裝類的實例變量和方法。而靜態嵌套類則不能。
調試代碼可以發現,內部類,Local內部類,匿名內部類的實例都持有一個外部封裝類實例的隱式引用;
而java對象序列化要求對象裡所有的對象成員都實現序列化接口。
所以,如果只有內部類實現序列化,而外部封裝類沒有實現序列化接口,就會在對內部類進行序列化的時候報出異常。