Java8新特性——lambda表达式

今天是高考的日子,是大四师兄师姐答辩毕业的日子。一代又来,一代又去。好久没写博客,借此特殊日子整理一下前不久学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新特性教程 

你可能感兴趣的:(lambda表达式,Java8新特性)