λ和属性外文翻译资料

 2022-05-05 09:05

CHAPTER 4

Lambdas and Properties

In this chapter, you learn about the new language feature introduced in Java 8 called lambda expressions, or lambdas. The chapter also covers JavaFX properties and binding APIs. The goal of this chapter is to demonstrate how lambdas and properties are used in the context of JavaFX GUI applications. Having said

this, I mainly concentrate on the common features that are used in most of the examples in this book and do not detail every lambda and properties feature.

To get a better idea of Javarsquo;s lambda roadmap, visit the following article by Brian Goetz, who is Oraclersquo;s Java Language Architect:

http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html

The term lambda derives from what is known in mathematics as lambda calculus. The general concepts from that field are used to derive the specific behaviors that have been added to Java, which are described in this chapter. Figure 4-1 shows the Greek letter lambda, which you sometimes see in connection with the topic.

Figure 4-1. The Greek symbol for lambda

Lambda

Java Lambda is based on JSR (Java Specification Request) 335, “Lambda Expressions for the Javatrade; Programming Language.” The feature was appropriately named after lambda calculus, the formal system in mathematical logic and computer science to express computations. JSR 335, better known as Project Lambda, comprised many features, such as expressing parallel calculations on streams (the Stream API).

copy; Carl Dea, Gerrit Grunwald, Joseacute; Pereda, Sean Phillips and Mark Heckler 2017 C. Dea et al., JavaFX 9 by Example, DOI 10.1007/978-1-4842-1961-4_4

103

A primary goal of lambdas is to help address the lack in the Java language of a good way to express functional programming concepts. Languages that support functional programming concepts have the ability to create anonymous (unnamed) functions, similar to creating objects instead of methods in Java. These function objects are commonly known as closures. Some common languages that support closures or lambdas are Common Lisp, Clojure, Erlang, Haskell, Scheme, Scala, Groovy, Python, Ruby, and JavaScript.

The main idea is that languages that support functional programming will use a closure-like syntax. In Java 8, you can create anonymous functions as first-class citizens. In other words, functions or closures can be treated like objects, so that they can be assigned to variables and passed into other functions. In order to mimic closures in the previous Java world (Java 1.1 to Java 7), you would typically use anonymous inner

classes to encapsulate functions (behavior) as objects. Listing 4-1 shows an example of an anonymous inner class that defines handler code for a JavaFX button when pressed (prior to Java 8).

Listing 4-1. A Buttonrsquo;s OnAction Set with an Anonymous Inner Class

Button btn = new Button();

btn.setOnAction(new EventHandlerlt;ActionEventgt;() { public void handle(ActionEvent event) { System.out.println('Hello World');

} });

You will notice that this code looks very verbose just to wire up a button. Buried deep in an anonymous inner class is a single line to output text. Wouldnrsquo;t it be nice to be able to express a block of code containing the behavior you want without the need of so much boilerplate code? Look no further. Java 8 solves this issue with the use of lambda expressions (closures). To see how it looks with Java 8 lambda expressions, letrsquo;s rewrite the button handler code. Listing 4-2 is the buttonrsquo;s EventHandler code rewritten as a Java 8 lambda expression.

Listing 4-2. A Buttonrsquo;s OnAction Set with a Lambda Expression

btn.setOnAction(event -gt; System.out.println('Hello World') );

Using lambda expressions not only makes code concise and easy to read, but the code is also likely to perform better. Actually, under the hood, the compiler is capable of optimizing code and likely to be able to reduce its footprint.

Lambda Expressions

As discussed, lambda expressions are Java 8rsquo;s version of closures. In the same way other languages create closures syntactically, you will also be able to reference them and pass them into other methods. In order to achieve this ability, you will later learn about functional interfaces. But for now, letrsquo;s look at the basic syntax for lambda expressions.

Syntax

There are two ways to specify lambda expressions. The following simple examples illustrate the general forms:

(param1, param2, ...) -gt; expression;

(param1, param2, ...) -gt; { /* code statements */ };

104

Lambda expressions begin with a list of parameters surrounded by parentheses, followed by the arrow symbol -gt; (a hyphen and a greater-than sign) and an expression body. Similar to Java methods, the parentheses are for parameters that are passed into an expression. The surrounding parentheses are

optional only if there is one parameter defined. When the expression doesnrsquo;t accept parameters (and is said to be empty), the parentheses are still required.

Separating the parameter list and the expression body is the arrow symbol. The expression body or code block may or may not be surrounded by curly braces. When the expression body doesnrsquo;t have

surrounding curly braces, it must consist of only one statement. When an expression is a one-line statement, it is evaluated and returned to the caller implicitly. Just remember that if the method requires a return type and your code block has curly braces, you must have a return statement. Listing 4-3 shows two equivalent lambda expressions, with

剩余内容已隐藏,支付完成后下载完整资料


lambda;和属性

在本章中,您将了解Java 8中引入的称为lambda表达式或lambda表达式的新语言功能。 本章还介绍了JavaFX属性和绑定API。 本章的目标是演示如何在JavaFX GUI应用程序的上下文中使用lambdas和属性。 说了我主要关注本书中大多数示例中使用的常见功能,并未详细说明每个lambda和属性功能。

要更好地了解Java的lambda路线图,请访问Oracle的Java语言架构师Brian Goetz的以下文章:

http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-final.html

术语lambda来源于数学中已知的lambda演算。 来自该字段的一般概念用于派生已添加到Java的特定行为,本章将对其进行描述。 图4-1显示了希腊字母lambda,有时您会看到与该主题相关的信。

LAMBDA

Java Lambda基于JSR(Java规范请求)335,“用于Javatrade;编程语言的Lambda表达式”。该功能以lambda演算(数学逻辑和计算机科学中用于表示计算的形式系统)为适当名称。 JSR 335,更名为Project Lambda,包含许多功能,例如在流上表达并行计算(Stream API)。

lambdas的主要目标是帮助解决Java语言中缺乏表达函数式编程概念的好方法。支持函数式编程概念的语言能够创建匿名(未命名)函数,类似于创建对象而不是Java中的方法。这些功能对象通常称为闭包。支持闭包或lambda表达式的一些通用语言是Common Lisp,Clojure,Erlang,Haskell,Scheme,Scala,Groovy,Python,Ruby和JavaScript。

主要思想是支持函数式编程的语言将使用类似闭包的语法。在Java 8中,您可以创建匿名函数作为一等公民。换句话说,函数或闭包可以像对象一样对待,以便可以将它们分配给变量并传递给其他函数。为了模拟前一个Java世界中的闭包(Java 1.1到Java 7),通常使用匿名内部

类将函数(行为)封装为对象。清单4-1显示了一个匿名内部类的示例,它在按下时(Java 8之前)为JavaFX按钮定义了处理程序代码。

清单4-1。 用匿名内部类设置按钮的OnAction

Button btn = new Button();

btn.setOnAction(new EventHandlerlt;ActionEventgt;() {

public void handle(ActionEvent event) {

System.out.println('Hello World');

} });

你会注意到这段代码看起来很冗长,只是为了连接一个按钮。 深埋在匿名内部类中是一行输出文本。 能够在不需要太多样板代码的情况下表达包含您想要的行为的代码块不是很好吗? 再看看。 Java 8通过使用lambda表达式(闭包)解决了这个问题。 为了看看它如何使用Java 8 lambda表达式,让我们重写按钮处理程序代码。 清单4-2是将按钮的EventHandler代码重写为Java 8 lambda表达式。

清单4-2。 使用Lambda表达式设置按钮的OnAction:

btn.setOnAction(event -gt; System.out.println('Hello World') );

使用lambda表达式不仅使代码简洁易读,而且代码也可能表现更好。 实际上,编译器能够优化代码,并且可能能够减少其占用空间。

Lambda表达式

正如所讨论的,lambda表达式是Java 8的闭包版本。 就像其他语言在语法上创建闭包一样,您也可以引用它们并将它们传递给其他方法。 为了达到这个能力,你将在后面学习功能接口。 但现在,我们来看看lambda表达式的基本语法。

语法

有两种方法可以指定lambda表达式。 以下简单的例子说明了一般形式:

(param1, param2, ...) -gt; expression;

(param1, param2, ...) -gt; { /* code statements */ };

Lambda表达式以括号括起来的参数列表开始,后跟箭头符号 - gt;(连字符和大于号)和表达式主体。与Java方法类似,括号用于传递到表达式中的参数。周围的括号是

只有在定义了一个参数时才是可选的。当表达式不接受参数(并且被认为是空的)时,括号仍然是必需的。

分离参数列表和表达式主体是箭头符号。表达式主体或代码块可能会或可能不会被大括号包围。当表达式体没有时

围绕花括号,它必须只包含一个语句。当表达式是单行语句时,它会被隐式评估并返回给调用者。请记住,如果该方法需要返回类型并且您的代码块具有大括号,则必须具有返回语句。清单4-3显示了两个等效的lambda表达式,带有和不带大括号。

清单4-3。 一个陈述带有明确的回报,另一个带有隐含的回报

// explicit return of result

Functionlt;Double, Doublegt; func = x -gt; { return x * x; }

// evaluates amp; implicitly returns result Functionlt;Double, Doublegt; func = x -gt; x * x;

double y = func(2.0); // x = 4.0

另外需要注意的是参数可以选择键入。编译器将根据上下文推断参数的类型。在清单4-3中,一个类型为java.util.function的函数接口。函数lt;T,Ugt;其中T类型转换为U类型。您将注意到参数x没有指定Double类型。这是因为Java 8编译器会根据功能接口定义来推断该类型。

我们来看一个将lambda表达式传递给方法的例子。一个简单的例子是使用setOnAction()方法设置JavaFX按钮。如前所述,编译器可以通过匹配方法的参数类型(其签名)和返回类型来计算出lambda参数。

有时为了便于阅读,您可以选择指定每个参数的类型。如果指定了类型,则需要在括号中包围参数列表。以下行指定JavaFX按钮的setOnAction()方法的lambda表达式的参数类型(ActionEvent)。

btn.setOnAction( (ActionEvent event) -gt; System.out.println('Hello World') );

您还会注意到,可以省略分号作为内部方法中的单行语句(如setOnAction()方法)。 最后要注意的一点是,如果你有一个参数传入你的lambda,括号可以省略。 以下是具有一个没有括号的参数(事件)的lambda表达式。

btn.setOnAction( event -gt; System.out.println('Hello World') );

作为刚刚讨论过的语法变体的回顾,清单4-4中的语句都是等效的lambda表达式。

清单4-4。 三个语法等价的Lambda表达式在JavaFX按钮上设置操作代码

btn.setOnAction( (ActionEvent event) -gt; {System.out.println(event); } ); btn.setOnAction( (event) -gt; System.out.println(event) ); btn.setOnAction( event -gt; System.out.println(event) );

方法参考

清单4-4显示了为JavaFX按钮的ActionEvent表达一个lambda表达式的三种方式,但是您是否知道有第四种方式?

通常在使用lambdas时,有一些方法将单个参数作为输入或单个值作为返回类型。 这是非常多余的,所以Java 8中的新方法是方法引用的概念。 方法引用基本上是语法糖,可以让你随后用更简单的方式调用方法

使事情更容易阅读。 例如,以下是使用方法引用的lambda表达式:

btn.setOnAction(System.out::println);

这段代码设置按钮上的动作,并且您会注意到它是一个简洁的版本,其行为与清单4-4的行为相同。 区别在于没有用于lambda的ActionEvent的输入参数以及System.out和println方法之间的异常双冒号。 双冒号称为范围操作符,它通过名称引用方法。 您还会注意到println方法的括号不存在。 如果您记得,每当一个lambda表达式将单个参数作为输入时,该参数将隐式传递给采用单个输入的方法println。 当然,这两种类型都必须是相同的。 示例中的事件对象将隐式调用toString()以将字符串传递给println方法。

除了本书的范围之外,还有其他方法引用类型。 有关其他用例场景,请参阅Javadoc文档。 查看关于方法参考的以下教程:

https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

可变捕获

通常,在函数式编程语言中,使用闭包(lambda表达式)允许您使用闭包范围外的变量。这些变量通常被描述为非局部变量或捕获变量,因为它们不是局限于lambda表达式或方法的范围。当这些非局部变量

在lambda表达式中使用,它们需要是不可变的。这是功能编程世界的一个关键原则。 Java 8编译器的新功能是能够引用超出匿名内部类或lambda表达式范围的变量。

在使用lambda表达式时,您可以选择引用在闭包函数之外作用的变量。通常,在Java 8之前,这些非本地变量需要是最终的(不可变的)。这种不可变状态使编译器能够更好地预测程序行为,从而能够优化代码。在Java Swing开发中,通常需要在匿名内部类方法(局部变量作用域)的范围内使用封闭作用域的变量时才会发生这种情况。为了遵守编译器规则,你必须声明一个变量为final。

Java 8编译器具有一种新功能,可以推断传入匿名内部类方法和lambda表达式的非本地变量的意图,然后将其转换为final(不可变)。要了解老派Java Swing开发人员(在Java 8之前)是如何用来接收编译时错误的,请看清单4-5。场景是一个按钮,它将在按下按钮后修改Swing JLabel组件的文本。在Java 8之前,代码将无法正确编译,因为标签变量需要声明为final。

功能接口

云计算的出现帮助重振了许多函数式编程语言。

显而易见,涉及极大数据集的解决问题存在范式转变。应用函数式编程技术时的一个典型用例是在以分布式方式执行计算时迭代数据集的能力,以便可以在节点或CPU之间共享负载

核心。相比之下,命令式编程语言收集数据,然后传递给一个严格的for循环

被处理。由于数据和代码是如何耦合的,这使得一个线程(核心)处理大量数据的负担很重。该问题需要分解,以允许其他线程(核心)参与计算,然后分配。

函数式编程的优点之一是能够以语法简洁的方式表达功能,但更重要的是能够将功能(lambda表达式)传递给方法。

能够将lambda表达式传递给方法通常会促进懒惰评估的概念。这种行为

与函数回调行为(异步消息传递)相同,其中调用被延迟(并因此“延迟”),直到稍后时间。懒惰评估的反面是急切的评估。使用懒惰评估通常会通过避免不必要的计算来提高性能。

另一个要讨论的重要话题是如何将功能接口用作Java语言中的闭包。 Java语言的设计者/架构师不是将函数实现为Java中的第一类类型,而是巧妙地将功能接口的概念定义为闭包。简而言之,功能接口基本上是一种单一的抽象方法(SAM)。功能接口的想法已经存在很长时间了。例如,那些使用Java线程的人会回想起使用Runnable接口,其中有一个带有void返回类型的run()方法。 单个抽象方法模式是Java 8的lambda表达式不可分割的一部分。 作为一个函数接口的例子,我使用一个抽象compute()方法创建了一个名为MyEquation的接口。 一旦它被创建,你可以用一个lambda表达式来声明和赋值变量。 清单4-7是一个具有单个抽象compute()方法的函数接口。

代码清单4-7。 使用单一抽象方法声明的功能接口compute()

// functional interface interface MyEquation {

double compute(double val1, double val2);

}

在创建一个功能接口后,您可以声明一个变量来分配一个lambda表达式。

清单4-8演示了将lambda表达式分配给函数接口变量。

代码清单4-8。

剩余内容已隐藏,支付完成后下载完整资料


资料编号:[463442],资料为PDF文档或Word文档,PDF文档可免费转换为Word

原文和译文剩余内容已隐藏,您需要先支付 30元 才能查看原文和译文全部内容!立即支付

以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。