我在網上做了一個小型的研究,並回顧了這個網站上的相關主題,但答案是矛盾的:有些人說這是不可能的,其他人說這是可能的,但是很危險。是否可以在沒有外部類的情況下序列化匿名類?
目標是傳遞匿名類的對象作爲RMI方法的參數。由於RMI的要求,這個類必須是可序列化的。這是沒有問題的,它很容易讓類Serializable。
但是我們知道內部類的實例持有對外部類的引用(並且匿名類是內部類)。因此,當我們序列化內部類的實例時,外部類的實例將被序列化以及一個字段。下面是問題出現的地方:外部類不是可序列化的,更重要的是 - 我不想序列化它。我想要做的只是發送匿名類的實例。
簡單的例子 - 這是一個RMI服務與接受Runnable接口的方法:
public interface RPCService {
Object call(SerializableRunnable runnable);
}
這裏是我想如何調用該方法
void call() {
myRpcService.call(new SerializableRunnable() {
@Override
public Object run {
System.out.println("It worked!");
}
}
}
正如你所看到的,我想要做的是向對方發送一個「動作」 - 系統A描述了應該在系統B上運行的代碼。這就像在Java中發送腳本一樣。
如果可能的話,我可以很容易地看到一些危險的後果:例如,如果我們從Runnable訪問一個字段或捕獲外部類的最終變量 - 我們會陷入麻煩,因爲調用者實例不存在。另一方面,如果我在Runnable中使用安全代碼(編譯器可以檢查它),那麼我看不出有什麼理由來禁止此操作。
所以,如果有人知道,如何writeObject()
和readObject()
方法應在匿名類或如何提及外部類transient
或解釋爲什麼它是在Java中不可能正確地重寫,這將是非常有益的。
UPD 另一個重要的事情要考慮:外部類中不存在將要執行的方法(系統B)的環境,這就是爲什麼有關它的信息應該完全排除,以避免NoClassDefFoundError
。
現在你沒有機會了。除了非常hardcore的方式,如發送類的字節碼到另一邊,並在那裏恢復 – talex 2014-10-17 10:35:18