Lamda表达式必须在方法内部吗?它们可以作为类的成员存在于方法之外吗

时间:2018-12-30 23:09:26

标签: java lambda

我试图看到,Scala和Java之间传递函数作为参数的区别。几年前,我搬到了Scala,与Java的联系并不多。我可以在方法外部使用Lambda表达式吗,如下所示?它可以编译并正常工作,但是有什么问题吗?到目前为止,我所看到的所有示例都在方法内部包含Lamdas。以下代码仅是示例,我知道您可以使用以下方法实现相同的操作 供应商界面。

@FunctionalInterface
public interface IFunc {

    String printMessage();
}


public class JavaFunc {

    public String message() {

        return functionA(functionB);
    }

    IFunc functionB = () ->  "Hi, I am functionB from Java, I am passed to functionA as a parameter.";

    public String functionA(IFunc funcB) {
        return funcB.printMessage();
    }

}

3 个答案:

答案 0 :(得分:6)

您可以在类中的任何地方声明lambda表达式

  

如果您在方法内部声明(类似于局部变量,则在方法内部定义作用域)

public String message() {

  IFunc functionB = () ->  "Hi, I am functionB from Java, I am passed to functionA as a parameter.";

    return functionA(functionB);
}
  

如果您在类中声明(类似于实例变量,可以直接在所有实例方法中访问并在静态区域中使用对象引用访问实例变量)

public class JavaFunc {

 IFunc functionB = () ->  "Hi, I am functionB from Java, I am passed to functionA as a parameter.";

public String message() {

    // use here functionB
    return functionA(functionB);
}

示例: Predicate和匿名内部类的lambda表达式

  

p1,p2在实例级别,p3,p4在本地

public class DemoMain {

Predicate<Integer> p1 = i -> i > 5;

Predicate<Integer> p2 = new Predicate<Integer>() {

    @Override
    public boolean test(Integer t) {
        // TODO Auto-generated method stub
        return false;
    }
};

public static void main(String args[]) {

    DemoMain m = new DemoMain();
    System.out.println(m.p1.test(10));
    System.out.println(m.p2.test(10));
}

public void m1() {

    System.out.println(p1.test(10));
    System.out.println(p2.test(10));

    Predicate<Integer> p3 = i -> i > 5;

    Predicate<Integer> p4 = new Predicate<Integer>() {

        @Override
        public boolean test(Integer t) {
            // TODO Auto-generated method stub
            return false;
            }
        };

    }

 }

答案 1 :(得分:2)

换句话说,lambda表达式也称为函数对象,因此,在可以使用普通对象的任何地方,也可以使用lambda:可以将它们定义为属性,可以将它们作为方法参数传递,等等。

public ExampleClass {
    //Initializing the consumer with our method reference (subset of lambdas)
    static Consumer<Integer> printer = System.out::println;

    public static void useLambda(Consumer<Integer> myIntegerPrinter, Integer value) {
         myIntegerPrinter.accept(value);
    }

    public static void main(String[] args) {
         // passing the lambda as parameter to useLambda
         useLambda(printer, 100);
    }
}

答案 2 :(得分:1)

记住Lambda的缩写。它仅用于方法定义,特别是用于功能接口。几乎在任何可以使用定义了某些功能的对象(具有简单逻辑)的地方,都可以轻松使用Lambda。一个很好的例子就是ActionListener。

没有lambda,我们可以说:

df.describe()['top']

使用lambda,我们可以将其简化为简单的表达式:

ActionListener al = new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(e.getActionCommand());
    }
};

很明显,它们之间是直接相关的。原始的'ActionEvent e'在辅助文件中被简单地声明为'e',因为编译器已经知道它的类型,并且类似地,我们可以通过在单行中声明它的作用来定义方法的主体。

现在,它们也可以作为参数传递,因为它们就像任何其他对象一样。例如,假设我们有一个JButton对象,该对象经常被赋予一个ActionListener。请注意,JButton具有方法JButton#addActionListener(ActionListener al)。现在,我们可以通过以下任意一种方式传递ActionListener:

ActionListener al = e -> System.out.println(e.getActionCommand());

所有这些在逻辑上都是等效的!