What's the nearest substitute for a function pointer in Java?

前端 未结 22 1554
太阳男子
太阳男子 2020-11-22 15:32

I have a method that\'s about ten lines of code. I want to create more methods that do exactly the same thing, except for a small calculation that\'s going to change one li

相关标签:
22条回答
  • 2020-11-22 16:13

    One of the things I really miss when programming in Java is function callbacks. One situation where the need for these kept presenting itself was in recursively processing hierarchies where you want to perform some specific action for each item. Like walking a directory tree, or processing a data structure. The minimalist inside me hates having to define an interface and then an implementation for each specific case.

    One day I found myself wondering why not? We have method pointers - the Method object. With optimizing JIT compilers, reflective invocation really doesn't carry a huge performance penalty anymore. And besides next to, say, copying a file from one location to another, the cost of the reflected method invocation pales into insignificance.

    As I thought more about it, I realized that a callback in the OOP paradigm requires binding an object and a method together - enter the Callback object.

    Check out my reflection based solution for Callbacks in Java. Free for any use.

    0 讨论(0)
  • 2020-11-22 16:14

    New Java 8 Functional Interfaces and Method References using the :: operator.

    Java 8 is able to maintain method references ( MyClass::new ) with "@ Functional Interface" pointers. There are no need for same method name, only same method signature required.

    Example:

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

    So, what we have here?

    1. Functional Interface - this is interface, annotated or not with @FunctionalInterface, which contains only one method declaration.
    2. Method References - this is just special syntax, looks like this, objectInstance::methodName, nothing more nothing less.
    3. Usage example - just an assignment operator and then interface method call.

    YOU SHOULD USE FUNCTIONAL INTERFACES FOR LISTENERS ONLY AND ONLY FOR THAT!

    Because all other such function pointers are really bad for code readability and for ability to understand. However, direct method references sometimes come handy, with foreach for example.

    There are several predefined Functional Interfaces:

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

    For earlier Java versions you should try Guava Libraries, which has similar functionality, and syntax, as Adrian Petrescu has mentioned above.

    For additional research look at Java 8 Cheatsheet

    and thanks to The Guy with The Hat for the Java Language Specification §15.13 link.

    0 讨论(0)
  • 2020-11-22 16:14

    Check out lambdaj

    http://code.google.com/p/lambdaj/

    and in particular its new closure feature

    http://code.google.com/p/lambdaj/wiki/Closures

    and you will find a very readable way to define closure or function pointer without creating meaningless interface or use ugly inner classes

    0 讨论(0)
  • Since Java8, you can use lambdas, which also have libraries in the official SE 8 API.

    Usage: You need to use a interface with only one abstract method. Make an instance of it (you may want to use the one java SE 8 already provided) like this:

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

    For more information checkout the documentation: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

    0 讨论(0)
  • 2020-11-22 16:16

    None of the Java 8 answers have given a full, cohesive example, so here it comes.

    Declare the method that accepts the "function pointer" as follows:

    void doCalculation(Function<Integer, String> calculation, int parameter) {
        final String result = calculation.apply(parameter);
    }
    

    Call it by providing the function with a lambda expression:

    doCalculation((i) -> i.toString(), 2);
    
    0 讨论(0)
  • 2020-11-22 16:17

    Method references using the :: operator

    You can use method references in method arguments where the method accepts a functional interface. A functional interface is any interface that contains only one abstract method. (A functional interface may contain one or more default methods or static methods.)

    IntBinaryOperator is a functional interface. Its abstract method, applyAsInt, accepts two ints as its parameters and returns an int. Math.max also accepts two ints and returns an int. In this example, A.method(Math::max); makes parameter.applyAsInt send its two input values to Math.max and return the result of that Math.max.

    import java.util.function.IntBinaryOperator;
    
    class A {
        static void method(IntBinaryOperator parameter) {
            int i = parameter.applyAsInt(7315, 89163);
            System.out.println(i);
        }
    }
    
    import java.lang.Math;
    
    class B {
        public static void main(String[] args) {
            A.method(Math::max);
        }
    }
    

    In general, you can use:

    method1(Class1::method2);
    

    instead of:

    method1((arg1, arg2) -> Class1.method2(arg1, arg2));
    

    which is short for:

    method1(new Interface1() {
        int method1(int arg1, int arg2) {
            return Class1.method2(arg1, agr2);
        }
    });
    

    For more information, see :: (double colon) operator in Java 8 and Java Language Specification §15.13.

    0 讨论(0)
提交回复
热议问题