30 minutes to learn Java8 and lambda expressions

  • 2020-06-19 10:17:15
  • OfStack

preface

Google released Android N developer Preview 1 this year and announced support for Java 8. We are finally able to use some of the language features of Java8 in Android development. Current support:

The default method lambda expression Many annotations

Today we will learn the lambda expression briefly.

Configuring the development environment

First you need to download and install JDK1.8.

If you want to use lambda expressions in Android development, you need to configure the Java 8 development environment in Android Studio.

Gradle file to configure app:

Turn on the jack compile option Set compilation options compatible to 1.8

android {
  defaultConfig {
    ...
    // open jack compile 
    jackOptions {
      enabled true
    }
  }
  ...
  // Set the compile option to Java1.8
  compileOptions {
    targetCompatibility 1.8
    sourceCompatibility 1.8
  }
}

For a variety of reasons, we may be using JDK version 1.7 or lower, but we want to learn to use lambda expressions. What do we do? Developers on Github have designed open source libraries that are compatible with lambda expressions to Java7, 6, and 5 retrolamda. How to configure it in Android Studio is not discussed here. See Gradle Retrolambda Plugin.

The first lambda expression

You'll be familiar with the following code. That's setting up a listening event for button.


 button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        Log.d("TAG"," Button clicked , Anonymous inner class ");
      }
    });

Analyze the code above, which sets the click-listening event for Button through the anonymous inner class. In other words, we created an implementation View.OnClickListener Object of the anonymous class of the interface. Anonymous inner classes are implemented onClick Methods. With the object of this anonymous class, we print the log when the user clicks the button.

But did you find out? The actual code above is Log.d ("TAG"," button clicked, anonymous inner class "); This 1 line of code reflects the disadvantage of using anonymous inner classes:

The readability is poor and does not reflect our intention directly and clearly. One line of logical code has several lines of template code.

The lambda expression solves these problems well:


button.setOnClickListener(view-> Log.d(TAG," Button clicked ,lambda expression "));

 view-> Log.d(TAG,"按钮被点击,lambda表达式")); That's the first lambda expression that we wrote.

lambda expressions are usually written as (argument)->(body) It's written in this format.


// Omit parameter type 
(arg1,arg2...) -> {body}

// Specify parameter type 
(Type1 arg1,Type2 arg2...)->{body}

In the lambda expression, the type of the parameter can be omitted. The Java compiler deduces the type of parameter based on the context of the expression. As shown in the figure above, the type of view is View.

The structure of the lambda expression

The parameters can be zero or more Parameter types can be specified or omitted (inferred from expression context) Parameters are enclosed in parentheses and separated by commas The expression body can be zero or more statements, enclosed in curly braces When the body of an expression has only one statement, the curly braces can be omitted When there are more than one statement in the body of an expression, the return type of the expression is the same as the return type 1 of the code block When the expression has only 1 statement, the return type of the expression is the same as the return type 1 of the statement

// zero 
 ()-> System.out.println("no argument");
 
//1 a 
 x->x+1

// two 
 (x,y)->x+y

// Omit parameter type 
 View.OnClickListener oneArgument = view->Log.d(TAG,"one argument");
 // Specify parameter type 
 View.OnClickListener oneArgument = (View view)->Log.d(TAG,"one argument");

// Multi-line statement 
// The return type is returned by the code block void
View.OnClickListener multiLine = (View view)->{
   Log.d(TAG,"multi statements");
   Log.d(TAG,"second line");
}

// The return type is the return type of the expression body statement int
(int x)->x+1

The type of lambda expression

As we all know, Java is a strongly typed language. All method parameters have types, so what type is the lambda expression?


 View.OnClickListener listener = new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        //...
      }
    };
    
 button.setOnClickListener(listener);

As shown above, we used to represent a method and reuse it by using the interface of a single method.

In the lambda expression, the same form as before is still used. We call it a functional interface (functional interface)

For example, View. OnClickListener used in the click response event of button is a functional interface.


public class View implements Drawable.Callback, KeyEvent.Callback,
    AccessibilityEventSource {
    ...
 public interface OnClickListener {
    void onClick(View v);
  }
  ...
  }

So what exactly is a functional interface?

A functional interface is an interface with only 1 abstract method. Used as a type to represent lambda expressions.

Many functional interfaces have been added to Java8 API:

接口名 参数 返回值 用途
Predicate T boolean 断言
Consumer T void 消费
Function T R 函数
Supplier None T 工厂方法
UnaryOperator T T 逻辑非
BinaryOperator (T,T) T 2元操作


Related articles: