简体   繁体   English

Java 中的传递方法

[英]Passing Methods in Java

I'm trying to accomplish passing a method in Java.我正在尝试完成在 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.所以,基本上,我在一个类中有方法,在上面的例子中是 B,我想将 B 的方法传递给 A 并将 B 的该方法的返回值存储在 A 上以供进一步处理。

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.我试图利用 Java 的method reference功能,但由于我不是每天都用 Java 编写代码,所以我很难在满足上述约束的同时正确地实现这一点。

Currently, I'm getting a incompatible types: invalid method reference error while I do the binding in the main method.目前,我在 main 方法中进行绑定时遇到了incompatible types: invalid method reference错误。

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 .这不能很好地工作,因为您要传递的方法具有完全不同的签名(methodOne 是(B, String) -> int (为什么在那里有大写​​的 I Int ,这是一个错字吗?),methodTwo 是(B) -> String ,而 methodThree 是(B, String, String) -> String

In java lambdas must fit a functional interface.在 java 中,lambdas 必须适合函数式接口。 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!这听起来真的像是一个 X/Y 问题:你有问题 X(你没有解释,我们不知道它是什么),你想:我知道! I'll use lambdas to abstract away the notion of 'a method'... and now you're asking questions about that.我将使用 lambdas 来抽象出“方法”的概念......现在你正在问这个问题。

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.问 X。因为即使假设你可以以某种方式将你的 3 个方法都放在同一个 lambda 类型中(你不能),你将无法调用它们。

Here's one more workable notion, but I have no idea if it solves your X because you didn't explain this:这是一个更可行的概念,但我不知道它是否能解决您的 X,因为您没有解释这一点:

@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?如果你想调用这个,你怎么知道特定的MyXThinger (你没有解释 X 是什么,所以我在这里不能想出一个好名字)如果你传递 2 个字符串就可以工作,如果你通过则崩溃还要别的吗? 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.您正在静态上下文中编写表达式B::methodOne

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 .因此,在静态上下文中, B::methodOne具有签名: (B, String) -> String What your bind method wants is (String) -> String , and these two are not compatible.你的绑定方法想要的是(String) -> String ,这两个不兼容。 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); 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.表达式b::methodOne ,其中 b 是B类型的变量,引用B的实际实例(使用new B()创建)确实具有签名(String) -> String所需。
  2. Make the methodOne method static , at which point it no longer has the invisible B instance parameter.methodOne方法设为static ,此时它不再具有不可见的B instance参数。

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;您必须调用a.bind而不是A.bind ,使用 A 和 B 作为类名非常混乱,您的绑定方法返回 Object (它应该返回A )等。解决这些问题的方法是学习基本的 java,我认为; trying to tackle those mistakes bit by bit seems unsuitable for what stackoverflow is for.试图一点一点地解决这些错误似乎不适合 stackoverflow 的用途。 Thus, I leave those as an exercise for you.因此,我将这些留给您作为练习。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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