First, let's look at a simple piece of code:
Interface ilambdatest1{
void print (String s);
public class LambdaTest1 {public
static void Main (string[] args) {
//implementation of the traditional inner class
Lambdause (New ILambdaTest1 () {
@Override public
void print (String s) {
System.out.println (s);
}
}, ' Hello World ';
}
public static void Lambdause (ILambdaTest1 lambda,string string) {
lambda.print (string);
}
}
This code, quite simply, is a static method that takes a ILambdaTest1 implementation and a string parameter, and calls the ILambdaTest1 implementation in the method to pass string arguments for processing, here is just an example, The most practical development is to pass Onactionlistener,onclicklistener when the button hits the event. This is only for demonstration purposes, regardless of the actual development role.
And then you'll find that the new inner class, in effect, is the System.out.println () method, and the most important problem is not to show the real purpose well.
So let's take a look at the implementation based on the lambda.
Interface ilambdatest1{
void print (String s);
public class LambdaTest1 {public
static void Main (string[] args) {
//implementation of the traditional inner class
Lambdause (s-> System.out.println (s), "Hello world.");
}
public static void Lambdause (ILambdaTest1 lambda,string string) {
lambda.print (string);
}
}
found that a word s->system.out.println (s) on the completion of the interface of the transfer, is not feel very magical, and a little difficult to understand, at the beginning I was confused, it doesn't matter, then we continue to look down. This blog mainly introduces how lambda expressions are used, and then publishes a blog to uncover the veil of the bottom of the lambda, so that you know what you know and why.
So what is a lambda expression?
To put it simply, it is an anonymous function.
Someone would ask. S->SYSTEM.OUT.PRINTLN (s) What do you mean by that remark? In fact, this sentence is the composition of lambda expressions. where s represents the parameter, System.out.println (s); means the implementation, in other words, the thing to do. What kind of S is that? It's obviously a string type here. The compiler will judge the type of s based on the context. For example, the first parameter accepted by the Lambdause method is the Ilambda interface, and the method inside the interface is print (String s), and the lambda expression is simply the implementation of the print function, where s-> The S in System.out.println (s) is the formal parameter to pass to the method print (String s), and System.out.println (s) is what the Print method does. What if the thing to do is not just a statement. It's a code block. Then add the curly braces s->{system.out.println (s);}, what if I'm passing a few arguments. Enclose the parameters to be passed in parentheses, such as (S1,S2)->{system.out.println (s); the},S1,S2 type can be determined by context, but you can also make it clear that, for example (String s1,string s2)-> {System.out.println (S1+S2);}, if there is no argument passed, then use an empty curly brace. such as: ()->{system.out.println ("Hello World.");
Just now our expression is and interface
Interface ilambdatest1{
void print (String s);
The Print method in the corresponding, then why can this corresponding. There is no explanation on the code. If the interface has only one method, you can also know that a lambda expression can only be mapped to that method, but if the interface has multiple methods how to determine it.
OK, lambda expressions are harsh on the interfaces that can be used to represent them, this interface can only have an abstract method, Yi, so that is not the same as the above guess, there can only be an abstract method, and then the lambda expression can only map to this method, think about it, If multiple really can't map.
To ensure that the interface can use lambda expressions, Java adds a new annotation, @FunctionalInterface, to decorate an interface with this annotation, and this interface can only have an abstract method. This type of interface is called a functional interface.
@FunctionalInterface public
Interface Function<t, r> {
R apply (t);
}
Because the interface in Java is enhanced, you can use the Defaule keyword to define the default implementation method in the interface, and the subclass of course can also be overridden, and the static method can be defined, both of which are not abstract. Therefore, the interface modified with @functionalinterface can still contain these two kinds of methods.
@FunctionalInterface
interface ilambdatest1{
void print (String s);
default void Moren () {
System.out.println ("Defalut");
}
static void Staticmethod () {
System.out.println ("static");
}
But if you define two abstract methods, the compiler will make an error.
Let's take a look at a simple example
@FunctionalInterface
Interface ilambdacaculator{
int result (int a,int b);
}
public class LambdaTest2 {public
static void Main (string[] args) {
System.out.println ("Add:" +lambdause ((a,b)- >a+b,12,14));
System.out.println ("Sub:" +lambdause (a,b)->a-b,12,14);
}
public static int Lambdause (Ilambdacaculator lambda,int a,int b) {return
lambda.result (A, b);
}
The results of the operation are:
Add:26
Sub:-2
The reader of the eye can see that the int result (int a, int b) method in the Ilambdacaculator interface has a return value, since (a,b)->a+b is the method that maps to the int result (int a, int b), That should also have the return value ah, in fact, we know that the return value is A+b, know that a single execution statement, the compiler will automatically return the execution result of the statement, we do not have to display the call, the display call will be wrong.
But if the-> is followed by {... Execute statement ...}, then the call that must be displayed is return.
System.out.println ("Sub:" +lambdause (a,b)->{return a-b;},12,14));
Now everyone should know how to use, then the following is a few lambda expressions than the inner class good things, concise, direct access to the subject, these are not discussed, let's discuss the lexical scope of the lambda. Simply put, the scope of the lambda in terms of code is the same as his scope, and there is no problem with variables hidden like inner classes. So what is a variable hiding problem?
As an example:
Import Java.util.function.Consumer;
public class Varaiblehide {
interface Iinner {
void printint (int x);
}
public static void Main (string[] args) {
int x =;
Iinner inner = new Iinner () {
@Override public
void Printint (int x) {
System.out.println (x);
}
};
Inner.printint (a);
}
You will then find that the x referenced in the inner class is not x in the main static method, that is, the x inside the inner class hides the outer x, but if the lambda expression is used.
You will notice that if you use X in parentheses, the error message is:
Then we change a variable A and then we output x.
Import Java.util.function.Consumer;
public class Varaiblehide {
interface Iinner {
void printint (int x);
}
public static void Main (string[] args) {
int x =;
Iinner inner = (a)->{system.out.println (x);};
Inner.printint (a);
}
The output is obviously 20.
So there is no hidden problem with lambda expressions, and this is the most error-prone use of this.
First look at an example:
Import Java.util.function.Consumer;
public class Varaiblehide {
interface Iinner {
void printtostring ();
}
public static void Main (string[] args) {
varaiblehide hide=new varaiblehide ();
Hide.test ();
}
public void Test () {
Iinner inner = ()->{system.out.println (this);
Iinner inner2=new Iinner () {
@Override public
void Printtostring () {
System.out.println (this);
}
@Override public
String toString () {return
"anonymous class toString";
}
};
Inner.printtostring ();
Inner2.printtostring ();
}
@Override public
String toString () {
//TODO auto-generated method stub return
"Outter toString";
}
}
The output is:
Outter ToString
Anonymous class ToString
So obviously the context in the lambda expression is the same as the context in which the lambda expression is located, but the inner class is different, and this often happens when you need to pass the context. For example, in Android, the click of a button is an event.
Button.setonclicklistener (New View.onclicklistener () {
@Override public
void OnClick (View v) {
Toast.maketext (This, "click me! "+v.getid (), Toast.length_short). Show ();
}
);
Then I'll tell you why the context of the lambda expression is the same as the context of the outside method.
We know that we want to use lambda expressions, we have to have a functional interface and its corresponding, that is not when we want to use, we have to define the interface.
In fact, Java has provided us with a part of the interface. These interfaces are in the Java.util.function package.
There are four types of summary:
1. Functional interfaces that accept parameters also provide return values function<p,t>
2. Supply-type interface does not accept parameters but has return value supplier<t>
3. Assertion-type interfaces are primarily used to judge predicate<p>
4. Consumer interface Accept parameter has no return value sonsumer<p>
The above four is the most basic, java.util.function and based on their other interface, you can go to see, the following a piece of code to let you look at these several interfaces. Here The example is purely to show that there is no other meaning.
Import java.util.ArrayList;
Import java.util.List;
Import Java.util.Random;
Import Java.util.function.Consumer;
Import java.util.function.Function;
Import Java.util.function.Predicate;
Import Java.util.function.Supplier; /** * eliminates the tedious internal class lambda expressions that can be used for functional interfaces, this interface has only one method, the annotation @functionalinterface limit * A total of four functional interfaces (which Java has built) 1. Functional interface That is, the Accept parameter also provides the return value Function<p,t> 2. Supply interface * Does not accept parameters but has a return value of supplier<t> 3. Assertion interface is mainly used to judge predicate * <P> * 4. Consumer interface Accept parameter has no return value Sonsumer * <P> * * @author Wangpeiyu */public class Lambdatest {public static void main (String
Args[]) {//test function//square Integer Ainteger = new Integer (12);
String string = "Outerline";
Function<integer, integer> function = a-> {return a * A;
};
SYSTEM.OUT.PRINTLN ("Functional Interface:" + function.apply (Ainteger));
Test Supply interface//Generate a random number supplier<integer> Supplier = ()-> {Random Random = new Random ();
return Random.nextint (45);
}; SYSTEM.OUT.PRINTLN ("Supply-type interface" + supplier.geT ());
Assertion-type interface//judge whether a number is greater than 0 predicate<integer> predicate = a-> {return a > 0;
};
SYSTEM.OUT.PRINTLN ("Assertion-type interface" + predicate.test (18)); Consumer interface//Output input parameter consumer<string> Consumer = a-> {System.out.println ("Consumer interface Internal" + a.length () + ""
+ string);
};
System.out.println ("Invoke Consumer Interface");
Consumer.accept ("Xiaofeixingjiekoucanshu");
list<string> list = new arraylist<> ();
List.stream (). Filter ((String s)-> {return s.length () < 10;
). Map (str-> str.length ()). ForEach (str2-> System.out.println (str2));
/** * Test the difference between the inner class and the lexical scope of the lambda expression/* lambdatest test = new Lambdatest ();
SYSTEM.OUT.PRINTLN ("Test the lexical scope of the lambda and inner classes");
Test.print ();
public void print () {consumer<string> Consumer = str-> {System.out.println (str + ' "+ this);
}; consumer<string> consumer2 = new consumer<string> () {@Override public void accept (String t) {Syste M.out.println (t + "" + thIS);
@Override public String toString () {return "inner class";
}
};
Consumer.accept ("Lambda");
Consumer2.accept ("anonymous Class");
@Override public String toString () {return "Outter class";
}
}
Here's how lambda expressions are used in Android. As you know, what you can use in Java is not necessarily available in Android Oh, think of Java running on the JVM, Android running on Dalvik or art virtual machines, which depends on whether the Android system supports it, So there are currently two ways to configure the virtual machine in Android:
Way one: Google is also the official recommendation:
1. In the Build.grade document of Module:app
Android {
defaultconfig{
..... Add this sentence
jackoptions.enabled=true;
}
2. Also in the Build.grade document of Module:app, in
android{
//Add the following
compileoptions{
sourcecompatibility org.gradle.api.JavaVersion.VERSION_1_8;
Targetcompatibility org.gradle.api.JavaVersion.VERSION_1_8
}
}
3. Click Sync to use it.
Attention:
When using this method, the Javac tool chain will be transformed into a new Jack tool chain, Javac tool chain: Javac (. java-->. Class)--> DX (. Class-->. Dex), Jack the tool chain Jack (. Java-->. Jack-->. Dex). You can't use apt at the same time when using Jack, if you use the apt annotation frame using butterknife, dagger and so on. So this time you can use mode two.
Mode 2:
1. Add code in four places under the project's Build.grade (project) document.
1.1
buildscript{
repositories{
//Add this sentence
mavencentral ()
}
dependencies{
//Add these two
words Classpath ' me.tatarka:gradle-retrolambda:3.6.1 '
classpath ' me.tatarka.retrolambda.projectlombok:lombok.ast:0 .2.3.a2 '
}
//Add this sentence
configurations.classpath.exclude group: ' Com.android.tools.external.lombok '
}
allprojects {
repositories {
//Add this sentence
mavencentral ()
}
}
2. An increase of two places in the Build.grade document of Module:app
1. Add these two words at the beginning
Apply plugin: ' com.android.application '
apply plugin: ' Me.tatarka.retrolambda '
2. In
android{
//Add the following
compileoptions{
sourcecompatibility org.gradle.api.JavaVersion.VERSION_1_8;
Targetcompatibility org.gradle.api.JavaVersion.VERSION_1_8
}
}
3. Then click Sync to use the lambda expression.
Button = (button) Findviewbyid (R.id.button);
Using lambda expressions, complete the processing of the Click event
button.setonclicklistener v->toast.maketext (This, "click me! "+v.getid (), Toast.length_short). Show ());
Very clear, perfect. The next article will introduce the underlying implementation of the lambda.