在变量Java中存储非静态方法

e4yzc0pl  于 2023-04-19  发布在  Java
关注(0)|答案(2)|浏览(114)

有没有办法把类的非静态方法存储在一个变量中?我猜如果可能的话,应该标记为final
C++的等价物是这样的:

#include <iostream>

class MyClass {
    
public:
    void function(int i) {
        
        std::cout << "Hello, World!" << std::endl;
        
    }
    
};

typedef void (MyClass:: *func_t)(int);

int main() {
    
    func_t func = &MyClass::function;
    
    MyClass A;
    
    (A.*func)(10);
    
    return 0;
}

我说得不够具体,我希望对象不像C++例子那样存储在变量中,这样,我可以改变对象,但保持相同的函数。

oprakyz7

oprakyz71#

一个类的方法引用被简单地命名为Class::method。就是这样…
但是你必须找到一个兼容的类型定义。使用java.util.function包,你可以使用Consumer s或Function s接口。注意,你的函数类型必须承认作为第一个参数,函数应该应用的对象。(这不同于instance_of_class::method,其中示例嵌入在表达式中)。
你也可以定义你自己的lambda函数签名(一个带有单个方法的接口)。
然后,您可以键入:

import java.util.function.Consumer;

public class A {
    int a;
    void print_a() {
        System.out.println(a);
    }

    public static void main(String[] argv)
    {
        A aa = new A();
        aa.a = 42;
        Consumer<A> method = A::print_a;
        method.accept(aa);
    }
}

请注意,调用引用使用lambda表达式的方法(acceptConsumer s,applyFunction s,以及您在自定义lambda接口中使用的任何方法)。

hgqdbh6s

hgqdbh6s2#

如果你定义了一个兼容的SAM类型,你可以简单地分配方法引用:

interface VoidIntFunc {
  void call(int i);
}

class MyClass {
    public void function(int i) {
        System.out.println("Hello, world!");
    }

    public static void main(final String... args) {
        final VoidIntFunc func = new MyClass()::function;
        func.call(42);
    }
}

幸运的是,Java已经定义了这个SAM类型:java.util.function.IntConsumer

class MyClass {
    public void function(int i) {
        System.out.println("Hello, world!");
    }

    public static void main(final String... args) {
        final IntConsumer func = new MyClass()::function;
        func.accept(42);
    }
}

如果你想要一个“未绑定”的方法引用,从类中获取方法的引用,并确保在SAM类型中定义方法,第一个参数具有类/示例的类型(当方法引用被调用时,这个参数将是this)。感谢user16320675在评论中指出这一点!

class MyClass {
    public void function(int i) {
        System.out.println("Hello, world!");
    }

    public static void main(final String... args) {
        final ToIntFunction func = MyClass::function;
        func.applyAsInt(new MyClass(), 42);
    }
}

其他选项包括使用Reflection获取java.lang.reflect.Method对象并调用它,或者查找java.lang.invoke.MethodHandle
调用Method示例的示例:

class MyClass {
    public void function(int i) {
        System.out.println("Hello, world!");
    }

    public static void main(final String... args) throws Exception {
        final Method method = MyClass.class.getMethod("function", int.class);

        final MyClass obj = new MyClass();
        method.invoke(obj, 42);
    }
}

方法句柄的示例类似,但需要稍微不同的API:

class MyClass {
    public void function(int i) {
        System.out.println("Hello, world!");
    }

    public static void main(final String... args) throws Throwable {
        final MethodHandle methodHandle = MethodHandles.publicLookup()
                 .findVirtual(MyClass.class, "function", MethodType.methodType(void.class, int.class));

        final MyClass obj = new MyClass();
        methodHandle.invokeExact(obj, 42);
    }
}

相关问题