我有一个方法,大约有十行代码。我想创建更多的方法来做完全相同的事情,除了一个会改变一行代码的小计算。这是一个传递函数指针来替换这一行的完美应用程序,但是Java没有函数指针。我最好的选择是什么?


当前回答

如果你只有一个不同的行,你可以添加一个参数,比如一个标志和一个If (flag)语句,它调用一行或另一行。

其他回答

当在一行中可以执行预定义数量的不同计算时,使用枚举是实现策略模式的一种快速而清晰的方法。

public enum Operation {
    PLUS {
        public double calc(double a, double b) {
            return a + b;
        }
    },
    TIMES {
        public double calc(double a, double b) {
            return a * b;
        }
    }
     ...

     public abstract double calc(double a, double b);
}

显然,策略方法声明以及每个实现的一个实例都定义在一个类/文件中。

如果有人试图传递一个函数,该函数使用一组参数来定义其行为,但使用另一组参数来执行,就像Scheme的:

(define (function scalar1 scalar2)
  (lambda (x) (* x scalar1 scalar2)))

参见Java中参数定义行为的传递函数

新的Java 8函数接口和方法引用使用::操作符。

Java 8能够使用“@ Functional Interface”指针维护方法引用(MyClass::new)。不需要相同的方法名称,只需要相同的方法签名。

例子:

@FunctionalInterface
interface CallbackHandler{
    public void onClick();
}

public class MyClass{
    public void doClick1(){System.out.println("doClick1");;}
    public void doClick2(){System.out.println("doClick2");}
    public CallbackHandler mClickListener = this::doClick;

    public static void main(String[] args) {
        MyClass myObjectInstance = new MyClass();
        CallbackHandler pointer = myObjectInstance::doClick1;
        Runnable pointer2 = myObjectInstance::doClick2;
        pointer.onClick();
        pointer2.run();
    }
}

那么,我们得到了什么?

function Interface——这是一个接口,无论是否带有@FunctionalInterface注释,它只包含一个方法声明。 方法引用-这只是特殊的语法,看起来像这样,objectInstance::methodName,不多不少。 用法示例-只是一个赋值操作符,然后调用接口方法。

您应该仅为侦听器使用函数接口,而且仅用于侦听器!

因为所有其他类似的函数指针都不利于代码的可读性和理解能力。然而,直接方法引用有时很方便,例如foreach。

有几个预定义的功能接口:

Runnable              -> void run( );
Supplier<T>           -> T get( );
Consumer<T>           -> void accept(T);
Predicate<T>          -> boolean test(T);
UnaryOperator<T>      -> T apply(T);
BinaryOperator<T,U,R> -> R apply(T, U);
Function<T,R>         -> R apply(T);
BiFunction<T,U,R>     -> R apply(T, U);
//... and some more of it ...
Callable<V>           -> V call() throws Exception;
Readable              -> int read(CharBuffer) throws IOException;
AutoCloseable         -> void close() throws Exception;
Iterable<T>           -> Iterator<T> iterator();
Comparable<T>         -> int compareTo(T);
Comparator<T>         -> int compare(T,T);

对于早期的Java版本,您应该尝试Guava库,正如Adrian Petrescu上面提到的,它具有类似的功能和语法。

如需进一步研究,请参阅Java 8 Cheatsheet

感谢戴帽子的家伙提供的Java语言规范§15.13链接。

从Java8开始,您可以使用lambdas,它在官方SE 8 API中也有库。

用法: 您只需要使用带有一个抽象方法的接口。 创建一个实例(你可能想使用java SE 8已经提供的实例),如下所示:

Function<InputType, OutputType> functionname = (inputvariablename) {
... 
return outputinstance;
}

有关更多信息,请查看文档:https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

谷歌Guava库正在变得非常流行,它有一个通用的Function和Predicate对象,它们已经在API的许多部分中使用了这些对象。