【问题标题】:getting a method object for a class with compile time checking (in java)获取具有编译时检查的类的方法对象(在 java 中)
【发布时间】:2011-08-10 02:48:33
【问题描述】:

我想得到一个类似这样的 Method 对象:

Method myMethod = MyClass.class.getDeclaredMethod("myDeclaredMethod",Arg1Class.class);

但是!我想在编译时检查方法“myDeclaredMethod”是否存在。我实际上不需要动态选择方法,我只需要对它的引用,这样我就可以将它传递给另一个方法……类似于 C 具有函数指针的方式。我想做这样的事情:

#include <stdio.h>

void helloWorld() {
    printf("hello\n");
}

void runFunction( void (myfunc)() ) {
    myfunc();
}

int main() {
    runFunction(helloWorld);
    return 0;
}

注意,如果我在调用“runFunction(helloWorld)”中输入错误“helloWorld”,我会收到编译时错误。如果可能的话,我希望在 Java 中出现同样的编译时错误。

【问题讨论】:

    标签: java reflection


    【解决方案1】:

    恐怕你在 Java 中做不到。

    然而,在 Java 中实现这一点的常用方法是定义一个接口,该接口将只声明一个方法,即您想要“作为参数传递”的方法,并在一个类中实现它。你的类必须实现你感兴趣的方法。当你想传递一个“引用”给方法时,你实际上传递了一个接口的实例。你可以在上面调用你的方法。

    一个例子可以解释这一点:

    interface Something {
        void doSomething();
    }
    
    class HelloWorld {
        void doSomething() {
            System.out.println("Hello world");
        }
    }
    
    class Main {
    
        void runFunc(Something s) {
            s.doSomething();
        }
    
        public static void main(String... args) {
            runFunc(new HelloWorld());
        }
    
    }
    

    问题是,如果你想调用另一个方法,你需要创建一个实现Something的新类

    【讨论】:

    • 感谢您简洁地回答问题并提供替代方案。我希望有另一种选择,因为这种情况下的接口不会帮助我......我试图(以最简单的方式)从主线程调用一个方法并让它在另一个线程中执行。到目前为止,我最好的方法是使用队列并将方法名称作为字符串传递。这是我拥有的最好的方法,因为我可能会在第二个线程中调用大约六种方法,并且我不想要一个 5 行的解决方案,我必须在我的代码中的六个地方重复。
    • @Vivien 我不明白为什么HelloWorld 没有实现interface Something,那不会引发编译错误吗?谢谢。
    【解决方案2】:

    这在 Java 中是不可能的:方法在 Java 中不是一等公民。

    但在 Scala 中是可以做到的!

    【讨论】:

    • 感谢您的正确回答。不过,我想指出,方法不是 C++ 中的一等公民(也就是说,它们不是对象),并且可以在编译时检查方法名称作为参数。因此,这部分答案并不是没有将方法名称作为方法调用的参数进行编译时检查的原因。
    【解决方案3】:

    您可以编写一个注释处理器,使用 JDK 中的私有 API 检查通过反射 API 调用的方法,并偶尔停止编译过程。 这在Compile-Time Checked Reflection API 中有详细说明,由 dp4j 完成。 如果将 dp4j 与 @Reflect 或 JUnit's @Test annotations 一起使用,则在“正常”调用方法时会进行编译时检查,如 myDeclaredMethod(new Arg1Class())

    【讨论】:

    • 听起来不错。我按照链接编译时间检查反射api,那里没有很多。不知道我应该找到什么,你能发布一个指向内容的链接吗?
    • 再次检查 - 文章已发布。
    猜你喜欢
    • 2023-04-01
    • 1970-01-01
    • 2011-11-10
    • 2011-02-14
    • 2010-12-26
    • 2012-06-01
    • 2011-09-01
    • 1970-01-01
    • 2016-03-11
    相关资源
    最近更新 更多