Java8新特性——lambda表达式

时间:2021-02-17 19:14:01

今天是高考的日子,是大四师兄师姐答辩毕业的日子。一代又来,一代又去。好久没写博客,借此特殊日子整理一下前不久学java8新特性时写的代码,留下痕迹。(本博客的代码根据 java8新特性教程 学习整理,加上个人的理解而成,关于某个新特性的介绍代码里的注释已经阐述清楚,故不再写文字介绍,直接看代码吧!)


    本篇介绍java8的新特性之一:lambda表达式。    

1.先定义两个功能性接口IConvert和IFormula,以作测试用:

  接口IConvert

/**
* 功能性接口
*/
@FunctionalInterface
interface IConvert<F,T>{

//将F类型转换成T类型
T convert(F from);
default void intValue2(){
}
default void intValue3(){
}
}

  接口IFormula:

/**
接口的默认方法
Java8允许开发者通过使用关键字 default 向接口中加入非抽象方法。
这一新的特性被称之为扩展方法。
*/
public interface IFormula{
double calculate(int num);

//扩展方法
default double sqrt(int a){
return Math.sqrt(a);
}
}

2. 使用lambda表达式:

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.junit.Test;

/*
* 为什么lambda表示式可以这样随意的使用?
* 每个lambda表达式都对应一个指定的类型,这个指定的类型是由接口确定的。该接口被称之为功能性接口,
* 它必须且恰好只包含一个抽象方法声明。被指定接口类型所对应的lambda表达式刚好和这个接口的抽象方法相匹配。
* 因为默认方法不是抽象的,因此可以在功能性接口中添加多个默认方法。
*
* 为了确保定义的接口达到要求,可以在接口上添加@FunctionalInterface注解。
* 编译器可以检测到该注解并判断你的接口是否满足条件,如果定义的接口包含多个抽象方法时,编译器便会报错。
*
*/
public class LambdaExpression {

@Test
public void testComparator(){
List<String> names = Arrays.asList("peter222", "anna3334444", "mike22442", "xenia");
//旧的写法
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}

});
System.err.println(names);
//[xenia, peter222, mike22442, anna3334444]

//lambda写法
Collections.sort(names, (s1, s2) -> s1.length() - s2.length());
System.err.println(names);
}

@Test
public void testIConvert(){
IConvert<String, Integer> convertor = (from) -> ( Integer.parseInt(from));
int converted = convertor.convert("123");
System.err.println(converted);
}

/**
* lambda范围 : 访问本地变量
*/
@Test
public void nativeVariable(){
//和匿名变量不同的是变量num不必强制的被声明为final。
//实际上,变量num在编译期是被隐式的转换为fianl类型的。

//final int num = 1;
int num = 1;
IConvert<Integer, String> converter =
(from) -> String.valueOf(from+num);

String s = converter.convert(123);
System.err.println(s);// 124
}

static int outerStaticNum = 11;
int outerNum = 22;

/**
* lambda范围 : 访问对象字段和静态变量
*/
@Test
public void visit_ObjectField_StaticVariable(){
//和访问本地变量相反,我们在lambda表达式里即可以读取也可以写入对象字段和静态变量.
//这一准则同样适用于匿名类。

IConvert<Integer, String> stringConverter1 = (from) -> {
outerNum = 23;
return String.valueOf(from);
};
System.err.println(stringConverter1.convert(outerNum)); // 22

IConvert<Integer, String> stringConverter2 = (from) -> {
outerStaticNum = 72;
return String.valueOf(from);
};
System.err.println(stringConverter2.convert(outerStaticNum)); // 11
}

/**
* lambda范围 : 不能访问接口默认方法
*/
@Test
public void visitInterfaceDefaultMethod(){
//默认方法不能被lambda表示式内部的代码访问。下面的代码不能通过编译:
//IFormula formula = (num) -> sqrt(num*100);
// err : The method sqrt(int) is undefined for the type LambdaExpression
}

public static void testRun(String[] args)
{
runPast();
runNow();

Runnable r = () -> { System.out.println("Runnable.........."); };
new Thread(r).start();
}
public static void runPast()
{
new Thread(new Runnable()
{

@Override
public void run()
{
System.out.println("以前的实现");

}
}).start();
}
/**
* Lambda表达式写法
* 函数式接口,Java 8引入了@FunctionalInterface注解来表明一个接口为一个函数式接口,函数式接口就是只包含一个抽象方法的接口。
*/
public static void runNow()
{
new Thread( () -> {
System.out.println("my lambda!");
} ).start();
}
}

详情请见这篇博客:  java8新特性教程