简体   繁体   中英

Passing Methods in Java

I'm trying to accomplish passing a method in Java.

Here is the birds-eye-view of what I'm trying to do as a dummy example:

public final class A {
  private String value;

  public A(String value) {
    this.value = value;
  }

  public final Object bind(Function<String, String> func) {
    this.value = func.apply(value);

    return this;
  }

  // Rest of the logic here to deal with `value`
}

public final class B {
  public static void main(String[] args) {
    A<T> a = new A("hello");
    a.bind(B::methodOne).bind(B::methodTwo);
  }

  private String methodOne(String s) {
    // method logic here

    return "haha";
  }

  private String methodTwo(String s) {
    // method logic here

    return "hi";
  }
}

So, basically, I've methods in a class, B in the above example, and I want to pass the methods of B to A and store the return value of that method of B on A for further processing.

I've tried to make use of method reference feature of Java but since I don't code daily with Java, I'm having a hard time getting my head around how to properly accomplish this while fulfilling the constraints above.

Currently, I'm getting a incompatible types: invalid method reference error while I do the binding in the main method.

Update

Made changes on my constraints of the program.

EDIT: The asker updated their question a lot after reading this answer. Crucially, originally each method had a completely different signature (different param types and amounts, and different return types). I'm leaving this answer untouched, be aware it is no longer particularly relevant to the question as it currently stands.

This doesn't work well because the methods you want to pass have completely different signatures (methodOne's is (B, String) -> int (why do you have a capital I Int in there, is that a typo?), methodTwo is (B) -> String , and methodThree is (B, String, String) -> String .

In java lambdas must fit a functional interface. It is not possible to have a functional interface for a variable number of input arguments.

With generics you can attempt to paper over the fact that the types of your inputs and output are different every time.

This really sounds like an X/Y problem: You have problem X (which you didn't explain and we don't know what it is), and you thought: I know! I'll use lambdas to abstract away the notion of 'a method'... and now you're asking questions about that.

But you're asking the wrong question. Ask X. Because even if hypothetically you could somehow fit your 3 methods all in the same lambda type (you can't), you would not then be able to invoke them.

Here's one more workable notion, but I have no idea if it solves your X because you didn't explain this:

@FunctionalInterface
public interface MyXThinger {
    Object result(Object... args);
}

If you want to invoke this, how would you know that the particular MyXThinger (you didn't explain what X is, so I can't come up with a good name here) works if you pass 2 strings, and crashes if you pass anything else? That's.. more or less why I find your problem description insufficient to give solid advice here.

You're writing the expression B::methodOne in a static context.

non-static methods have an invisible parameter, called 'the receiver': It's the instance.

So, in a static context, B::methodOne has the signature: (B, String) -> String . What your bind method wants is (String) -> String , and these two are not compatible. Therefore, this does not work.

There are two ways to fix it:

  1. create an instance: B b = new B(); a.bind(b::methodOne); B b = new B(); a.bind(b::methodOne); . The expression b::methodOne , where b is a variable of type B referencing an actual instance of B (as created with new B() ) DOES have the signature (String) -> String as required.
  2. Make the methodOne method static , at which point it no longer has the invisible B instance parameter.

Your code is also littered with rookie mistakes; you must call a.bind and not A.bind , using A and B as class names is extremely confusing, your bind method returns Object (it should return A ), etc. The way to fix those is to learn basic java, I think; trying to tackle those mistakes bit by bit seems unsuitable for what stackoverflow is for. Thus, I leave those as an exercise for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM