C++11:Class 将函数指针(模板化的非成员函数)存储到 Java
C++11: Class storing a function pointer (templatized, non-member function) to Java
我主要不是 Java 程序员...我想找到相应的 Java 语法 class 将函数指针(模板化)存储为变量。函数指针指向一个函数"outside"class。原始代码在 C++11 中:
#include <memory>
template <typename T>
using p_function = T(*)(T, T, T);
template <typename T>
class A
{
private:
int k;
p_function<T> pf;
public:
A() { pf = NULL; k = 0; }
A(p_function<T> pf_, int k_) { pf = pf_; k = k_; }
T getF(const T a1, const T a2, const T a3) const { return pf(a1, a2, a3); }
};
template <typename T>
T f1(T x, T y, T z) { return x + y + z; }
template <typename T>
T f2(T x, T y, T z) { return x - y - z; }
int main()
{
A<double> aa (f1<double>, 1.0);
double val= aa.getF(1.0, 2.0, 3.0);
}
思考问题,接口的使用是否合理?
public interface Function <T> {
T pf(T x, T y, T z);
}
或者,有没有更好的办法? Java发展较快,可能比几年前有"straighter"建设。有几个我无法加入的要求。我可以在 Java 中索取简短的代码示例吗?非常感谢您的帮助。
我不确定我是否正确回答了您的问题,但请查看 this Whosebug post。
在java中有几个关于如何实现函数指针的答案。
编辑
我的 C++ 经验不足,无法提供代码示例。
编辑 2
根据我上面提到的post,你可以尝试这样的事情:
public class WithFunction {
//Empty constructor, can be left out
public WithFunction () {...}
//The function you want to reference
public int myReferencedFunction () {...}
}
然后
public class MethodCaller {
public static Object call (Object theObject, String methodName) {
return theObject.getClass().getMethod(methodName).invoke(theObject);
//catch Exceptions
}
}
那你就可以了
public static void main (String [] args) {
WithFunction obj1 = new WithFunction();
Object result = MethodCaller.call (obj1, "toString");
int result = (int) MethodCaller.call (obj1, "myReferencedFunction");
}
通知:
你需要捕获很多异常。需要强大的错误处理能力..
如果你使用一个接口,你也可以多次实现它,应该有你需要的自由度
使用 java 8. 使用 "functional" 接口(实际上),其中接口仅定义一个函数。
为了不过度使用现有的功能 class,引入你自己的名字。
@FunctionalInterface
public interface TriFunction<T> {
T apply(T x, T y, T z);
}
用 FunctionalInterface 注释标记它是一种防止添加第二个函数等的做法。
class Foo {
public static Bar hop(Bar x, Bar y, Bar z) { ... }
}
TriFunction<Bar> pf = Foo::hop;
TriFunction<Integer> pg = (x, y, z) -> x + y + z;
Bar bara = pf.apply(a, b, c);
对于原始类型,最好定义自己的接口而无需泛型参数类型。以上 pg
需要 3 次将包装器对象拆箱,并再次将其装箱到一个对象。
包 java.util.function
包含许多功能接口,例如 BinaryOperator
和 IntBinaryOperator
。
在Java8中,可以使用方法引用。此处有更多信息:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
基本上,Java 8 为接口提供了一种特殊的方法 属性,它们可以(有点)像函数指针一样使用。您可以将 lambda 或方法引用分配给此类类型的对象。
例如,与您的问题有些相关:
public class HelloWorld {
public interface Function <T> {
T op(T x, T y);
}
public static class Functions {
static int add(int x, int y) { return x + y; }
static int sub(int x, int y) { return x - y; }
}
static Function<Integer> f1, f2; // <-- "function pointer"
public static void main(String []args) {
f1 = Functions::add; // <-- static method reference
f2 = Functions::sub; // <-- static method reference
System.out.println("Test: " + f1.op(1,2) + ", " + f2.op(1,2));
}
}
如您所料,此代码打印出来:
Test: 3, -1
所以你的问题的这一部分应该有效。但是,您定义泛型加法的部分问题更大,因为 Java 不允许您重载运算符“+”。所以以下将不会在 Java 中编译:
T add(T x, T y) {
return x + y; // compile error -> no '+' defined for T
}
如果您需要 T
作为基本类型,您需要为每个要使用的基本类型定义 f1
和 f2
。另见这个问题:Can I do arithmetic operations on the Number baseclass?
我主要不是 Java 程序员...我想找到相应的 Java 语法 class 将函数指针(模板化)存储为变量。函数指针指向一个函数"outside"class。原始代码在 C++11 中:
#include <memory>
template <typename T>
using p_function = T(*)(T, T, T);
template <typename T>
class A
{
private:
int k;
p_function<T> pf;
public:
A() { pf = NULL; k = 0; }
A(p_function<T> pf_, int k_) { pf = pf_; k = k_; }
T getF(const T a1, const T a2, const T a3) const { return pf(a1, a2, a3); }
};
template <typename T>
T f1(T x, T y, T z) { return x + y + z; }
template <typename T>
T f2(T x, T y, T z) { return x - y - z; }
int main()
{
A<double> aa (f1<double>, 1.0);
double val= aa.getF(1.0, 2.0, 3.0);
}
思考问题,接口的使用是否合理?
public interface Function <T> {
T pf(T x, T y, T z);
}
或者,有没有更好的办法? Java发展较快,可能比几年前有"straighter"建设。有几个我无法加入的要求。我可以在 Java 中索取简短的代码示例吗?非常感谢您的帮助。
我不确定我是否正确回答了您的问题,但请查看 this Whosebug post。
在java中有几个关于如何实现函数指针的答案。
编辑
我的 C++ 经验不足,无法提供代码示例。
编辑 2
根据我上面提到的post,你可以尝试这样的事情:
public class WithFunction {
//Empty constructor, can be left out
public WithFunction () {...}
//The function you want to reference
public int myReferencedFunction () {...}
}
然后
public class MethodCaller {
public static Object call (Object theObject, String methodName) {
return theObject.getClass().getMethod(methodName).invoke(theObject);
//catch Exceptions
}
}
那你就可以了
public static void main (String [] args) {
WithFunction obj1 = new WithFunction();
Object result = MethodCaller.call (obj1, "toString");
int result = (int) MethodCaller.call (obj1, "myReferencedFunction");
}
通知:
你需要捕获很多异常。需要强大的错误处理能力..
如果你使用一个接口,你也可以多次实现它,应该有你需要的自由度
使用 java 8. 使用 "functional" 接口(实际上),其中接口仅定义一个函数。
为了不过度使用现有的功能 class,引入你自己的名字。
@FunctionalInterface
public interface TriFunction<T> {
T apply(T x, T y, T z);
}
用 FunctionalInterface 注释标记它是一种防止添加第二个函数等的做法。
class Foo {
public static Bar hop(Bar x, Bar y, Bar z) { ... }
}
TriFunction<Bar> pf = Foo::hop;
TriFunction<Integer> pg = (x, y, z) -> x + y + z;
Bar bara = pf.apply(a, b, c);
对于原始类型,最好定义自己的接口而无需泛型参数类型。以上 pg
需要 3 次将包装器对象拆箱,并再次将其装箱到一个对象。
包 java.util.function
包含许多功能接口,例如 BinaryOperator
和 IntBinaryOperator
。
在Java8中,可以使用方法引用。此处有更多信息:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
基本上,Java 8 为接口提供了一种特殊的方法 属性,它们可以(有点)像函数指针一样使用。您可以将 lambda 或方法引用分配给此类类型的对象。
例如,与您的问题有些相关:
public class HelloWorld {
public interface Function <T> {
T op(T x, T y);
}
public static class Functions {
static int add(int x, int y) { return x + y; }
static int sub(int x, int y) { return x - y; }
}
static Function<Integer> f1, f2; // <-- "function pointer"
public static void main(String []args) {
f1 = Functions::add; // <-- static method reference
f2 = Functions::sub; // <-- static method reference
System.out.println("Test: " + f1.op(1,2) + ", " + f2.op(1,2));
}
}
如您所料,此代码打印出来:
Test: 3, -1
所以你的问题的这一部分应该有效。但是,您定义泛型加法的部分问题更大,因为 Java 不允许您重载运算符“+”。所以以下将不会在 Java 中编译:
T add(T x, T y) {
return x + y; // compile error -> no '+' defined for T
}
如果您需要 T
作为基本类型,您需要为每个要使用的基本类型定义 f1
和 f2
。另见这个问题:Can I do arithmetic operations on the Number baseclass?