如何访问“拥有”的实例; java中的方法?

发布于 2024-10-29 03:46:06 字数 505 浏览 0 评论 0原文

在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 一起传递,但这似乎是额外的负担。

in java, is it possible to access the instance to which a method belongs, given only the method?

for example:

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

my feeling is that methods belong to classes, not instances of a class, so the answer is no, but maybe there's some sneaky reflection technique i don't know about. i could always pass 'this' along with method foo, but that seems like extra baggage.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

雪化雨蝶 2024-11-05 03:46:06

取自

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

当将要调用的实际参数与底层方法的形式参数相匹配时,方法允许发生扩大转换,但如果发生缩小转换,它会抛出 IllegalArgumentException。

您可以调用 Method#invoke 但您需要从方法文档中获取要调用该方法的对象的实例:

调用底层方法
由这个 Method 对象表示,在
指定的对象与
指定参数。个人
参数自动解包
为了匹配原始形式参数,
以及原始和参考
参数以方法为准
根据需要进行调用转换。
如果底层方法是静态的,
那么指定的 obj 参数是
被忽略。它可能为空。

如果形参的个数
底层方法所需的是
0,提供的 args 数组可能是
长度为 0 或 null。

如果底层方法是
实例方法,使用以下方式调用
动态方法查找,如文档中所述
Java 语言规范,
第二版,第 15.12.4.4 节;在
特别的,压倒性的基于
目标对象的运行时类型将
发生。

如果底层方法是静态的,
声明该方法的类是
如果尚未初始化,则已初始化
已初始化。

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

因此,TL:DR 除非您拥有想要调用该方法的实际对象,否则这是不可能的。

Taken from

A Method provides information about, and access to, a single method on a class or interface. The reflected method may be a class method or an instance method (including an abstract method).

A Method permits widening conversions to occur when matching the actual parameters to invoke with the underlying method's formal parameters, but it throws an IllegalArgumentException if a narrowing conversion would occur.

You can call Method#invoke but you will need the instance of the object you want to call the method on, from the method doc:

Invokes the underlying method
represented by this Method object, on
the specified object with the
specified parameters. Individual
parameters are automatically unwrapped
to match primitive formal parameters,
and both primitive and reference
parameters are subject to method
invocation conversions as necessary.
If the underlying method is static,
then the specified obj argument is
ignored. It may be null.

If the number of formal parameters
required by the underlying method is
0, the supplied args array may be of
length 0 or null.

If the underlying method is an
instance method, it is invoked using
dynamic method lookup as documented in
The Java Language Specification,
Second Edition, section 15.12.4.4; in
particular, overriding based on the
runtime type of the target object will
occur.

If the underlying method is static,
the class that declared the method is
initialized if it has not already been
initialized.

If the method completes normally, the
value it returns is returned to the
caller of invoke; if the value has a
primitive type, it is first
appropriately wrapped in an object.
However, if the value has the type of
an array of a primitive type, the
elements of the array are not wrapped
in objects; in other words, an array
of primitive type is returned. If the
underlying method return type is void,
the invocation returns null.

So the TL:DR is unless you have the actual object you want you call the method on, it is not possible.

时光沙漏 2024-11-05 03:46:06
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();
    }

}

给你所属的类。实例不拥有方法。

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();
    }

}

gives you the owning Class. An instance doesn't own methods.

赠佳期 2024-11-05 03:46:06

您可以这样做,但在您的示例中,正确的方法是使用接口,因为这似乎就是您想要的:您想要传递 ClassB 知道如何操作的对象。

   interface Callback {
      void foo();
   }

   public class ClassA implements Callback {...}

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

You can do this, but the proper way in your example would be the use of an interface, because that seems to be what you want: You want to pass in an object that ClassB knows how to operate on.

   interface Callback {
      void foo();
   }

   public class ClassA implements Callback {...}

   public class ClassB {
     public void receiveMethod(Callback cb) {...}
   }
天涯离梦残月幽梦 2024-11-05 03:46:06

这就像问:

“给定一个来自苹果园的苹果,哪棵树拥有这个苹果?”

答案是:

“不知道,因为所有苹果树都结苹果,所以它可能属于任何树”。

...换句话说 - 您必须提供一个将调用该方法的实例

编辑

从您的评论中,我推测您正在寻找替代方法观察者模式。您说您不喜欢观察者模式的混乱,并且它对您来说不够“通用”。

我认为它可能是现有的最不混乱的模式之一,并且根据定义,接口是最通用的!

所以,也许这是您遇到的实施问题。幸运的是,我已经在 SO 上发布了 JAVA 中的观察者实现,以展示它是多么强大和优雅。

多态性和接口Java(可以使用多态性来实现接口...为什么?)

事实上:反射比使用接口更混乱,因为你无法在编译时保证您正在调用方法实例的对象,甚至支持该方法! (没有一些错误检查代码)。与接口相比,甚至不可能出现这个问题。

This is like asking:

"Given an apple from an Apple orchard, which tree owns this apple?"

The answer to which is:

"No idea, since all apple trees produce apples, it could belong to any tree".

... in other words - you must supply an instance from which the method will be called

EDIT

From one of your comments, I gather you are looking for an alternative of the Observer pattern. You say you don't like the messiness of the Observer pattern and that it is not "generic" enough for you.

I would argue that it is probably one of the least messiest patterns in existence, AND interfaces are by definition as generic as things get!

So, perhaps its an implementation problem you're having. Luckily, I have already posted on SO an Observer implementation in JAVA, to demonstrate how powerful and elegant it is.

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

In fact: reflection is messier than using an interface, since you can't guarantee at compile time that the type of Object you are invoking an instance of a Method on, even supports that method! (without some error checking code). Versus with interfaces, its not possible to even have that problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文