Java8 Lambda表达式

LorenzoTrow 8年前
   <h3><strong>第一个Lambda表达式</strong></h3>    <p>在Lambda出现之前,如果我们需要写一个多线程可能需要下面这种方式:</p>    <pre>  <code class="language-java">Runnable runnable = new Runnable() {              @Override              public void run() {                  System.out.println("Hello runnable");              }          };          ...   thread.start();</code></pre>    <p>上面的例子如果改成使用Lambda就会简单许多:</p>    <pre>  <code class="language-java">Runnable noArgs = ()->System.out.println("Hello Lambda!~");  ...   thread.start();</code></pre>    <p>Lambda表达式是一个匿名函数,将行为像数据一样传递,表达式使用 -> 将参数和主体分开, -> 前面是参数部分,后面这是主体部分。</p>    <h3><strong>Lambda的其它形式</strong></h3>    <pre>  <code class="language-java">BinaryOperator<Long> add = (x,y)->x+y;   //OR   BinaryOperator<Long> add = (Long x,Long y)->x+y;   //OR   BinaryOperator<Long> add = (Long x,Long y)->{      x+y;   };</code></pre>    <ul>     <li> <p>Lambda表达式使用 () 表示没有参数。</p> </li>     <li> <p>如果Lambda表达式中只包含一个参数,可省略掉 () 。</p> </li>     <li> <p>如果Lambda表达式的主题是一段代码块,需要使用 {} ,该代码块与普通的Java代码块并无区别,也可以返回或抛出异常。</p> </li>     <li> <p>如果参数的类型可以由编译器推断得出可以省略参数类型,当然你也可以加上。</p> </li>    </ul>    <p>以上就是Lambda表达式的所有形式了。</p>    <p>那么问题来了:</p>    <p>BinaryOperator<Long> add = (Long x,Long y)->x+y; <strong>是个什么意思?</strong></p>    <p>这行代码并不是讲个数字相加,而是创建了一个函数,用来计算两个数字相加的结果。而add的类型是 BinaryOperator<Long> ,它也不是两个数字的和,而是将两个数字相加的那段代码。下面的例子展示如何使用这个变量:</p>    <pre>  <code class="language-java">BinaryOperator<Long> add = (Long x,Long y)->x+y;    Long res = add.apply(3L, 4L);    System.out.println("res="+res);//输出:res=7</code></pre>    <h3><strong>函数接口</strong></h3>    <p><strong>函数接口是只有一个抽象方法的接口,用作Lambda表达式的类型。</strong></p>    <p>如 Runnable 就是一个函数接口。</p>    <p>新建一个我们自己的函数接口:</p>    <pre>  <code class="language-java">public interface AddOperator<T,D> {      long add(T one,D two);  }</code></pre>    <p>使用:</p>    <pre>  <code class="language-java">AddOperator<Long,Long> addOperator = ( x, y)->x +y;   System.err.println("Custom function listener res= "+addOperator.add(34L, 65L));</code></pre>    <h3><strong>目标类型</strong></h3>    <p>目标类型是指Lambda表达式所在上下文环境的类型。比如,将Lambda表达式赋值给一个局部变量,或传递给一个方法作为参数,局部变量或方法参数的类型就是Lambda表达式的目标类型。</p>    <h3><strong>final</strong></h3>    <p>如果我们在匿名内部类中引用了所在方法中的局部变量,这是需要局部变量是 final 的。</p>    <p>在Lambda中我们不需要将引用的外部局部变量声明为 final 的,但是该变量只能被赋值一次。</p>    <p>下面的例子中如果我们去掉注释,对name再次赋值,则无法通过编译,并显示出错信息: <strong>local variables referenced from a Lambda expression must be final or effectively final.</strong></p>    <p>Lambda表达式引用的局部变量必须是final或即成事实的final。</p>    <pre>  <code class="language-java">String name = getUserName();  //name="hi";  button.addActionListener(event->System.out.println("name="+name));</code></pre>    <h3><strong>类型推断</strong></h3>    <p>Lambda表达式的类型推断是Java7中就引入的目标类型推断的扩展。</p>    <p>java7中的类型推断:</p>    <pre>  <code class="language-java">List<String> list= new ArrayList<>();</code></pre>    <p>上例中我们并没有指定ArrayList的范型类型,而是根据list的类型,推断出了ArrayList的范性类型。</p>    <p>如: AddOperator<Long,Long> addOperator = ( x, y)->x +y;</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/49b751742ffc</p>    <p> </p>