如何在java中访问'拥有'方法的实例?

时间:2011-04-01 23:47:17

标签: java reflection methods instance

在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...
    }
}

我的感觉是方法属于类,而不是类的实例,所以答案是否定的,但也许有一些我不知道的偷偷摸摸的反射技术。我总是可以通过方法foo传递'this',但这似乎是额外的包袱。

4 个答案:

答案 0 :(得分:2)

取自

  

方法提供有关类或接口上的单个方法的信息和访问权限。反射方法可以是类方法或实例方法(包括抽象方法)。

     

方法允许在将实际参数与基础方法的形式参数进行匹配时进行扩展转换,但如果发生缩小转换,则会抛出IllegalArgumentException。

你可以调用Method#invoke但是你需要从方法doc中调用方法的对象的实例:

  

调用基础方法   由此Method对象表示   带有的指定对象   指定的参数。个人   参数自动解包   匹配原始形式参数,   以及原始和参考   参数取决于方法   必要时调用转换。   如果底层方法是静态的,   那么指定的obj参数是   忽略。它可能为空。

     

如果正式参数的数量   基础方法所要求的是   0,提供的args数组可以是   长度0或null。

     

如果基础方法是   实例方法,使用它调用   动态方法查找,如中所述   Java语言规范,   第二版,第15.12.4.4节;在   特别是,基于的压倒一切   目标对象的运行时类型   发生。

     

如果基础方法是静态的,   声明方法的类是   初始化,如果它还没有   初始化。

     

如果方法正常完成,则   它返回的值返回给   调用者;如果值有   原始类型,它是第一个   适当地包裹在一个物体中。   但是,如果值的类型为   一个原始类型的数组,   数组的元素没有包装   在物体;换句话说,一个数组   返回原始类型。如果   底层方法返回类型为void,   调用返回null。

所以TL:DR除非你有你想要调用方法的实际对象,否则它是不可能的。

答案 1 :(得分: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();
    }

}

为您提供拥有的课程。实例不拥有方法。

答案 2 :(得分:0)

这就像问:

“鉴于来自苹果园的苹果,哪棵树拥有这个苹果?”

答案是:

“不知道,因为所有的苹果树都会生产苹果,它可能属于任何树木。”

...换句话说 - 你必须提供一个从中调用方法的实例

修改

从你的一条评论中,我发现你正在寻找Observer模式的替代方案。你说你不喜欢观察者模式的混乱,并且它对你来说不够“通用”。

我认为它可能是现存中最不起眼的模式之一,并且界面定义为通用的东西!

所以,也许这是你遇到的一个实施问题。幸运的是,我已经在JAVA上发布了一个Observer实现,以展示它是多么强大和优雅。

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

实际上:反射比使用接口更麻烦,因为您无法在编译时保证您调用Method实例的Object类型,甚至支持该方法! (没有一些错误检查代码)。与界面相比,它甚至不可能出现这个问题。

答案 3 :(得分:0)

你可以这样做,但你的例子中的正确方法是使用interface,因为这似乎是你想要的:你想传入一个ClassB知道如何操作的对象

   interface Callback {
      void foo();
   }

   public class ClassA implements Callback {...}

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