2010-07-25 18 views
2

我現在已經寫了一些藍牙應用程序,但我從來沒有見過this particular approach直到最近。在這個例子中,他們使用device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });,這在我看來只是說BluetoothSocket bs = createRfcommSocket(...當我使用getClass.getMethod(...)時,它是「反射」嗎?

是什麼他們的做法

Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class }); 
sock = (BluetoothSocket) m.invoke(device, Integer.valueOf(1)); 

和礦山

sock = createRfcommSocket(..... 

之間的區別是有沒有理由使用一個或其他?

謝謝

+0

是createRfcommSocket的一種靜態方法嗎? – Carsten 2010-07-25 23:11:50

+0

@Carsten我認爲它不能是靜態的,因爲在這種情況下,invoke()的第一個爭論應該是null。 – Gopi 2010-07-25 23:16:59

+1

我很確定那個寫這個其他主題的人說:「我甚至嘗試過這樣做,作爲一個瘋狂的最後努力,看看它是否有所作爲。」不要提倡這是一種編寫代碼的理智方式:) – Affe 2010-07-26 00:02:53

回答

1

是的,使用getClass等是反射。

不同之處在於,如果您錯誤地輸入了方法名稱或發生類似的錯誤,那麼您可以從IDE和編譯器獲得幫助,而代碼的作者是獨立的。

也許他們處於調用just的方法在編譯時不可用的情況,這可能是在允許在運行時加載新插件的軟件上下文中的情況。但在這種情況下,您不希望看到將方法名稱和其他細節硬編碼到代碼中。

你的榜樣的文字文本看起來就像編程可憐我。

+0

這是針對Android操作系統中的錯誤或怪癖的特定解決方法,但通常它確實是糟糕的編程。 – idolize 2010-07-26 18:05:23

1

不知道確切的細節,其中一個原因,我可以提供的是,他們的做法有一種關於它的鴨打字。不管對象的編譯時間類是什麼,只要它有一個具有正確簽名的方法,就可以調用它。

現在一般我認爲它的緣故鴨打字不Java中的一個很大的成語。但是,這種方法可能有其他理由。特別是,這意味着這段代碼不會對編譯時間依賴於device的類。例如,這可以是循環依賴的一種方式,而其他方式則使編譯步驟更鬆散地耦合。

從更廣泛的意義上講,如果你的方法工作然後我沒有看到任何問題。使用反射是通常在本質上是解決方法的東西,你不能在一個更地道的方式做。

1

請注意,反射使得使用不屬於SDK的平臺的實現細節非常容易,因爲它繞過了編譯時檢查。永遠不應該有這樣的反思來訪問平臺API,除了向後兼容的情況下,你希望你的應用在沒有該API的平臺的老版本上運行。每當你這樣做時,你都應該非常小心地確保你所訪問的內容實際上是SDK的一部分。

1

這裏的答案是正確的,但使用反思的具體原因是作爲解決方案圍繞createRfcommSocketToServiceRecord問題。

我這樣做的理由來自其他人說它正在解決他們的連接問題。

請參閱herehere瞭解更多信息。我認爲這個bug已經修復,因爲createRfcommSocketToServiceRecord(沒有任何解決方法)在我的Android OS 2.2 Nexus One上正常工作。

+0

但連接到嵌入式設備時仍不起作用 – Mazze 2011-07-27 14:51:01

0

如果您正在檢查該運行時對象中是否存在該方法 - 沒有拋出任何異常(比如說基於給定變量的runt-time父類不同 - 比如外部驅動程序),那麼您必須添加更多行無論如何..直接調用這樣的方法或按名稱檢索導致異常在缺席的情況下拋出。

IF NOT - then

不應該這樣寫。如果您已經有權訪問該對象,則調用method..period。

@mxrider,很高興你做到了正確的方式......這可能是濫用反射API的一個很好的例子。但是您可能想要考慮一下原作者是否想要解決上面我想解釋的情景。

0

只有反射方法適用於爲我做多點藍牙連接? 做多點連接有困難的人應該嘗試反射方法。