2011-04-01 65 views
2

在Java中,是否有可能訪問方法所屬的實例,只給出方法?如何訪問在java中擁有一個方法的實例?

例如:

public class ClassA { 
    private ClassB instanceB = new ClassB(); 
    // ... 
    private void sendMethod() { 
     instanceB.receiveMethod(foo); 
    } 
    public void foo() {} 
} 

public class ClassB { 
    public void receiveMethod (Method method) { 
     Object o = foo.getInstanceOwner(); // just made that part up... 
    } 
} 

我的感覺是方法屬於類,一類沒有實例,所以答案是否定的,但也許有一些偷偷摸摸的反射技術,我不知道。我總是可以通過'this'和foo方法一起傳遞,但這看起來像是額外的行李。

+1

我不記得能夠通過類似的方法在我的Java ...然後再次,我有一段時間沒有使用它。 – tster 2011-04-01 23:50:16

+2

你不能發送這樣的方法; java沒有函數指針,lambdas,委託或類似的東西。 – Kevin 2011-04-01 23:54:02

+0

hm,看起來你是對的 - 我來自一個主要的ActionScript背景,你可以*傳遞類似的方法。 – ericsoco 2011-04-01 23:56:57

回答

2

一種方法提供了有關信息,並獲得,在一個類或接口的單個​​方法兩者。反射方法可以是類方法或實例方法(包括抽象方法)。

一個方法允許在將實際參數與基礎方法的形式參數調用匹配時擴展轉換,但是如果發生縮小轉換,則會引發IllegalArgumentException。

您可以撥打Method#invoke,但你會需要你想調用的方法的對象的實例,從方法DOC:

調用由此Method對象表示的基本方法 ,上 指定的對象與 指定的參數。單獨的 參數被自動解包爲 以匹配原始形式參數 並且原始參考和參考 參數都根據需要受方法 調用轉換的支配。 如果底層方法是靜態的, 然後指定obj參數是 忽略。它可能爲空。

如果底層方法所需的形式參數 的數目是 0,所供給的args數組可以是 長度爲0或空的。

如果底層方法是 實例方法,它是使用動態 方法查找如 記錄調用的Java語言規範, 第二版,部分15.12.4.4;在 特別是,基於 的覆蓋目標對象的運行時類型將發生 。

如果底層方法是靜態的,即 聲明的方法 初始化,如果它已不是 初始化類。

如果該方法正常完成,則返回的 值將返回給調用方的 調用方;如果該值具有 基元類型,則首先將 合適地包裝在對象中。 然而,如果值具有 一個基本類型的數組的類型,所述陣列的 元件不包裹在對象 ;換言之,返回原始類型的數組 。如果 基礎方法返回類型爲void,則 的調用返回null。

所以TL:DR是除非你有你想要的實際對象你打電話的方法,這是不可能的。

0
public class ClassA { 
    private ClassB instanceB = new ClassB(); 
    // ... 
    private void sendMethod() { 
     Method m = ClassA.class.getMethod("foo", null); 
     instanceB.receiveMethod(m); 
    } 
    public void foo() {} 
} 

public class ClassB { 
    public void receiveMethod (Method method) { 
     Class c = method.getDeclaringClass(); 
    } 

}

給你所屬的類。一個實例不擁有方法。

+0

謝謝,但是這提供了擁有方法的* class *,而不是實例。 – ericsoco 2011-04-02 00:10:41

+0

對不起,沒有看到你的筆記在底部。這是我的感覺 - 實例不擁有自己的方法。 – ericsoco 2011-04-02 00:13:43

0

這就像問:

「?鑑於從蘋果園,這樹擁有這個蘋果一個蘋果」

這個問題的答案是:

「不知道,因爲所有的蘋果樹生產蘋果,它可以屬於任何樹」。

...換句話說 - ,你必須提供一個實例從該方法將被調用

編輯

從您的意見之一,我收集你正在尋找一種替代的觀察者模式。你說你不喜歡Observer模式的混亂,並且它對你來說不夠「通用」。

我認爲它可能是現存最不最麻煩的模式之一,並且接口在定義上與事物一樣通用。

所以,也許是它的一個實現問題。幸運的是,我已經在JAVA上發佈了Observer實現,以演示它的強大和優雅。

Polymorphism and Interfaces in Java (can polymorphism be used to implement interfaces...why?)

事實上:反射比混亂使用接口,因爲你不能在編譯時該對象的類型要調用一個方法的一個實例保證,甚至支持這種方法! (沒有一些錯誤檢查代碼)。與接口相比,它甚至不可能有這個問題。

+0

@J T,我不是指Observer模式的混亂,我指的是不可避免地(?)在實現Observer接口的類的更新方法中發生的混亂。在ActionScript中,爲觀察者傳遞一個事件類型和一個方法給調度器(即Observable),並且調度器在調度指定類型的事件時直接調用該方法。在Observer.update中,觀察者必須打開傳入的對象(例如Event的類型)以確定如何響應。 – ericsoco 2011-04-02 01:56:03

+0

還有一點需要注意:可以認爲AS的實現不如OOP,因爲它將偵聽器的方法暴露給另一個對象(調度器),該對象保持對這些方法的引用。但它爲使用觀察者模式提供了一個非常乾淨的API。我只是試圖在Java中實現類似乾淨的(以我的觀點來看)。 – ericsoco 2011-04-02 02:01:06

+1

@ericsoco:請參閱我對上一個問題的回答http://stackoverflow.com/q/4129280/591057 – 2011-04-02 02:33:17

0

你可以這樣做,但在你的例子中正確的方法是使用interface,因爲這似乎是你想要的:你想傳入一個ClassB知道如何操作的對象。

interface Callback { 
     void foo(); 
    } 

    public class ClassA implements Callback {...} 

    public class ClassB { 
    public void receiveMethod(Callback cb) {...} 
    } 
+0

我需要比接口更通用的東西...我不想在這裏詳細討論,因爲這是提問,不討論想法的地方(我已經被投票了爲此之前)。但基本上我試圖找到一種解決Observer.update內不可避免發生的混亂的方法。 – ericsoco 2011-04-02 00:15:38

+0

@ericsoco:嗯?觀察者模式的混亂?它可能是現存最乾淨的模式之一。 Plus界面被定義爲通用的。查看我的更新後的文章 – 2011-04-02 01:11:23

+0

您可以自由地將您想要在您自己的課程中調用它的實例包裝在Method對象中。 – 2011-04-02 04:21:51

相關問題