Anatomy of Java8's lamda expression 01

"The author takes you to analyze Java8's lamda expression 01"

 

In fact, from the birth of Java8 to the present, the author has not officially used Java8 and lamda in any project for more than 3 years. Time flies, when we are still at the syntax level of Java6 and Java7, the official version of 9 is coming to us, I really feel ashamed, so the author took the time to sort out some expression syntaxes of lamda, and also prepared Soften it in the project.

 

First of all, let's take a look at the advantages of using Lamda. I believe that no one is willing to sacrifice stability to try early adopters . The 2-word summary of lamda's changes at the grammatical level is: brevity . Therefore, lamda expressions can be understood as a concise way of expressing passable anonymous functions.

 

The composition of lamda is as follows:

Figure 1 The structure of the lamda expression

 

The structure of the lamda expression consists of three parts, the first is the parameter list of lamda, the second is the arrow symbol, and the last is the function body of lamda. So see now, let's start with something real, how to use Lamda expressions, think about it, before Java8, when we used threads, in most cases, it was implemented by anonymous classes, then see See how to retrofit with lamda expressions:

/* Anonymous class usage */
new Thread(new Runnable() {
 @Override
 public void run() {
  System.out.println(Thread.currentThread().getId());
 }
}).start();
/* lamda usage */
new Thread(() -> System.out.println(Thread.currentThread().getId())).start();

 

What was your first feeling? I feel clean and concise anyway, because I don't need to waste time writing boilerplate code anymore . You may be wondering, what should I do if my function body consists of multiple lines? The basic syntax of a lamda expression is as follows:

Runnable t1 = () -> System.out.println(Thread.currentThread().getId());
/* If the function body consists of multiple lines, use curly braces {} */
Runnable t2 = () -> {
 for (int i = 0; i < 10; i++) {
  // ...
 }
};

 

When you learn a new skill, you must consider where you can use it happily. lamda can be used on functional interfaces . A functional interface is slightly abstract. In short, it is an interface that is defined with the @FunctionalInterface annotation and contains only one abstract method. This is the so-called functional interface. If the interface marked with the @FunctionalInterface annotation contains If there are 2 abstract methods, the compiler will inform "Invalid '@FunctionalInterface' annotation; CompareObj is not a functional interface".

 

Of course, abstract methods in functional interfaces are also called function descriptors, because the method signatures of abstract methods in interfaces are basically the signatures of lamda expressions. Just imagine, if a functional interface contains N abstract methods, when we use a lamda expression, how does the compiler distinguish which method signature should correspond to the signature of the lamda expression?

@FunctionalInterface
public interface CompareObj {
 public boolean compare();
 public boolean compare2();
 /* CompareObj comObj=()->true;编译器如何清楚所对应的具体方法? */
}

 

 再回到函数式接口这个话题,刚才笔者也说了,被@FunctionalInterface标记的接口我们可以称之为函数式接口,但这个注解并不是必须的(Java8中Runnable以及Callable等接口已经标注了该注解),但好的编码习惯只会对实际的开发过程中带来意想不到的帮助。那么接下来我们就来定义一个函数式接口,并在它上面使用Lamda表达式:

@FunctionalInterface
public interface Compare {
 public boolean compare(String str1, String str2);
 /* Java8允许接口中定义实现 */
 public static void main(String[] args) {
  testCompare((String str1, String str2) -> str1.equals(str2), "a", "b");
 }
 public static boolean testCompare(Compare c, String str1, String str2) {
  return c.compare(str1, str2);
 }
}

 

除了可以自定义函数式接口,Java8 API也为开发人员提供了一些较为常用和常见的函数式接口:Predicate、consumer、Funtion,这些接口都被包含在java.util.funtion包下。

 

当然笔者并不会全部对这些接口进行介绍,感兴趣的同学可以自行研究其用法,笔者仅挑 Predicate<T>接口进行演示。在该接口中包含一个返回值为boolean类型的test()的抽象方法,我们可以使用该函数式接口来验证一个涉及类型为T的布尔表达式,如下所示:

Predicate<String> p = (String str) -> StringUtils.isEmpty(str);
System.out.println(p.test("lamda"));

 

 

《笔者带你剖析Java8的lamda表达式01》

 

其实Java8从诞生到至今,3年多的时间里笔者一直没有在任何项目中正式使用到Java8和lamda。时光飞逝,当我们还停留在Java6和Java7的语法层面时,9的正式版也即将来到我们身边,真的是感觉到惭愧,所以笔者抽空整理了一下lamda的一些表达式语法,同时也准备在项目中柔和进它。

 

首先我们来看看,使用Lamda有什么好处,没好处的事情相信谁也不愿意牺牲稳定性去尝鲜。lamda对语法层面的改变2个字总结就是:简洁。因此可以把lamda表达式理解为简洁的表示可传递的匿名函数的一种方式。

 

lamda的构成,如下所示:

图1 lamda表达式的构成结构

 

lamda表达式的构成结构由3部分构成,首先是lamda的参数列表,其次是箭头符号,最后是lamda的函数主体。那么看到现在,我们先来点实在的东西,如何使用Lamda表达式,思考一下,在Java8之前,我们使用线程的时候,大部分情况下,都是通过匿名类的的方式进行实现,那么看看如何使用lamda表达式进行改造:

/* 匿名类的用法 */
new Thread(new Runnable() {
 @Override
 public void run() {
  System.out.println(Thread.currentThread().getId());
 }
}).start();
/* lamda用法 */
new Thread(() -> System.out.println(Thread.currentThread().getId())).start();

 

你的第一感觉是什么?反正我的感觉清爽和简洁,因为再也不必要那浪费时间去编写样板代码。你可能会产生疑问,如果我的函数主体由多行构成的时候应该怎么办呢?lamda表达式的基本语法如下:

Runnable t1 = () -> System.out.println(Thread.currentThread().getId());
/* 如果函数主体由多行构成,则使用花括号{} */
Runnable t2 = () -> {
 for (int i = 0; i < 10; i++) {
  // ...
 }
};

 

学了新技能,就要考虑在哪里能够欢快的使用,lamda可以使用在函数式接口上。函数式接口眨一听,略带抽象,简单来说,就是一个被定义了@FunctionalInterface注解且仅包含一个抽象方法的接口,这就是所谓的函数式接口,那么被@FunctionalInterface注解标记的接口如果包含了2个抽象方法,编译器会告知“Invalid '@FunctionalInterface' annotation; CompareObj is not a functional interface”。

 

当然函数式接口中的抽象方法也被称之为函数描述符,因为接口中抽象方法的方法签名基本上就是lamda表达式的签名。你试想一下,如果一个函数式接口中包含N个抽象方法,我们在使用lamda表达式时,编译器如何区lamda表达式的签名应该对应哪一个方法签名呢?

@FunctionalInterface
public interface CompareObj {
 public boolean compare();
 public boolean compare2();
 /* CompareObj comObj=()->true;编译器如何清楚所对应的具体方法? */
}

 

 再回到函数式接口这个话题,刚才笔者也说了,被@FunctionalInterface标记的接口我们可以称之为函数式接口,但这个注解并不是必须的(Java8中Runnable以及Callable等接口已经标注了该注解),但好的编码习惯只会对实际的开发过程中带来意想不到的帮助。那么接下来我们就来定义一个函数式接口,并在它上面使用Lamda表达式:

@FunctionalInterface
public interface Compare {
 public boolean compare(String str1, String str2);
 /* Java8允许接口中定义实现 */
 public static void main(String[] args) {
  testCompare((String str1, String str2) -> str1.equals(str2), "a", "b");
 }
 public static boolean testCompare(Compare c, String str1, String str2) {
  return c.compare(str1, str2);
 }
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326560705&siteId=291194637