2

尋找了很長時間的Java對象,但沒有找到一個任何回答:發送一個未知的類

我有一臺服務器,我有一個客戶端。服務器應通過ObjectInputStreamObjectOutputStream接收對象。這已經適用於服務器上已知的任何class。 現在我想發一個Objectclass服務器不知道。他只知道該班的接口。那顯然失敗了......

我該如何避免ClassNotFoundException?我認爲接口是解決方案。我只想訪問我所知道的接口函數,但Java想要這個類。

謝謝。

+0

該接口是否存在於服務器上? – christopher 2013-02-26 13:19:25

+0

是的,接口在服務器上。 – manima 2013-02-26 13:22:48

回答

3

有沒有辦法。爲了能夠在一個對象上執行一個方法,你需要擁有該對象的具體類的字節碼。它的界面不夠。

+0

那麼,這不是我喜歡聽到的;-) – manima 2013-02-26 13:24:01

+0

所以然後我會發送.class到服務器並加載它,在接收我的對象之前。 – manima 2013-02-26 13:27:15

+0

@JBNizet「沒有辦法」聽起來不像我的答案。實際上,有一些方法,即在發送對象之前發送'.class'文件。 – 2013-02-26 13:28:35

0

只有當JVM加載了該類時,某些類的對象纔可能存在於JVM中。可能不是發送未知類型的對象,最好發送一些描述對象的着名數據結構,即HashMap。所以,與其做:

MySecretClass o = new MySecretClass(); 
o.setFoo ("Hello, World!"); 
o.setBar (123); 
send (o); 

你做到以下幾點:

Map o = new HashMap(); 
o.put ("foo", "Hello, World!"); 
o.put ("bar", 123); 
send (o); 
+0

我已經想到了這一點 - 但我想訪問該對象中的方法,而不僅僅是其中的數據。 – manima 2013-02-26 13:22:24

+0

@MatthiasNiemann如果你需要方法,那麼你肯定需要類的'.class'文件在服務器上可用,因爲方法的邏輯是在類中,而不是在對象中。考慮從客戶端發送'.class'文件到服務器。 – 2013-02-26 13:24:10

+0

謝謝。已經害怕這樣做,但如果沒有其他方式.. – manima 2013-02-26 13:27:46

0

您需要在服務器上的特定類的字節碼,這樣你想象它不會工作。

您可以發送客戶端和服務器都知道的類的代理對象。代理將包含服務器未知的類的對象,並且它的類將作爲字節數組存儲在代理中。代理類將爲Externalizable並且將使用Classloader.defineClass在代理對象反序列化時(使用具有從客戶端傳遞的類定義的字節數組)的動態創建服務器JVM中的未知類。它不會很快,但可以優化,就像不要發送和加載一個類的定義兩次等。

如果您需要直接調用接口特定的方法直接從客戶端傳遞的對象,使代理實現您的接口並使用代理對象(java.lang.reflect.Proxy/InvocationHandler)上的動態代理模式將調用傳遞給以前未知類的代理對象。

這是相當複雜的,但我可以這樣做,我相信。

+0

根據不同的答案進行一些討論後,值得注意的是,還需要發送類的依賴關係。 – MarianP 2013-02-27 17:47:53