疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java8 Lambda 表达式 学习


 

   

  最近 在整RxJAVA 想它用到我们开发的项目中来, 用起来之后发现Rxjava 这种写法真的是很牛B的

  特别是配合 新的java8 的lambda 表达式的时候,

  ok 下面来学习下 lambda 表达式.

  lambda 是java8 的一个新特性, 其实java8 出来也有些时间了, 可是还是不够普及

  额 先看看使用起来是什么样子吧:

  // 老的用法

  Thread thread1 = new Thread(new Runnable() {

  @Override

  public void run() {

  LogUtil.d("test lambad");

  }

  };

  // lambad表示 用法

  Thread thread2 = new Thread(() -> LogUtil.d("test lambad"));

  写起来 方便简单多了,

  在实现只含有一个抽象方法的接口时,即函数式接口时 就可以使用 lambad 表达式

  如上面 的Runnable 接口, 它只有一个 run方法

  就可以 () ->LogUtil.d("test lambda") 代替runnable 了

  不仅可以作为参数时 使用, 在写成员变量的时候也可以用:

  private Runnable mRunnable = () -> LogUtil.d("");

  ok 上面了解了 lambda 的大概使用范围, 以后遇到 只有一个 方法的接口时 都可以考虑使用lambad表达式

  ok 下面详细说说 lambda 表达式相关语法:

  (parameters) -> expression

  (parameters) -> statement

  (parameters) -> { statements; }

  好像没啥乱用

  举例子来说明吧:

  省略参数类型

  int x, int y) -> { return x + y; };

  (x, y) -> { return x + y; };

  类型可以省略 , 要么全部省略, 要么都不省略

  1个参数时, 可以省略括号

  (String text) -> { System.out.println(text); };

  (text) -> { System.out.println(text); };

  text -> { System.out.println(text); };

  上面3种都可以

  省略()时 就不能带类型了String text -> { System.out.println(text); }; // 错误

  函数体多行时需要大括号

  (int i) -> {

  int prod = 1;

  for(int n = 0; n < 5; n++) prod *= i;

  return prod;

  };

  函数体只有一行的话可以省略大括号

  text -> System.out.println(text);

  ssert语句不能省略带括号,比如: s -> { assert !s.isEmpty(); };

  return语句不能省略带括号,比如:(x, y) -> return x -y; // 错误

  只有一行代码而且有返回值的可以省略return,会返回该行代码计算结果

  (x, y) -> { return x -y; };

  (x, y) -> x -y;

  eturn要和大括号一起省略,比如:(x, y) -> { x - y; }; // 错误

  没有参数没有返回值的空函数

  () -> {};

  用于Lambda时 非final对象 和 非成员变量对象是不可以引用的

  如下例子:

  Integer i = 100;

  i = 111;// 这样 i 是可变的

  Thread thread1 = new Thread(new Runnable() {

  @Override

  public void run() {

  LogUtil.d(TAG, "test " + i);

  }

  });

  Thread thread2 = new Thread(() -> LogUtil.d(TAG, "test lambad" + i));

  这样编译器会报错, 错误信息 就合 匿名内部了的一样, 只能引用fainal 对象

  Lambda和匿名类区别

  public class LambdaTest {

  public LambdaTest() {

  Function func1 = new Function() {

  @Override

  public void func() {

  System.out.println("Anon Class: " + this.getClass());

  }

  };

  Function func2 = () -> System.out.println("Lambda Exp.: " + this.getClass());

  }

  }

  打印出来的 this 是不一样的

  lambda 很少用this

  ok 上面就是一些 关于lambda 一下简单内容,

  在看lambda的时候还款到 关于java8 接口相关的一些东西

  在很多情况下, 接口写好了一般都不能动, 否则 修改一下接口, 那么继承自这个接口的类都需要修改,

  但是在java8 中, 对接口做了特殊处理, 使得接口有了更多的扩展性

  可以看看如下例子:

  public interface IntefaceA {

  void fun1(int a);

  }

  public class ClassA implements IntefaceA {

  @Override

  public void fun1(int a) {

  }

  }

  后面接口需要做一些修改, 但是又不想修改 ClassA 类

  那么就可以使用接口的默认方法了:

  如下:

  public interface IntefaceA {

  void fun1(int a);

  default int fun2(int a, int b) {

  return a + b;

  }

  }

  public class ClassA implements IntefaceA {

  @Override

  public void fun1(int a) {

  }

  }

  public class ClassB implements IntefaceA {

  @Override

  public int fun2(int a, int b) {

  return a + b + b;

  }

  @Override

  public void fun1(int a) {

  }

  }

  这样 ClassA无需做任何修改了, 页实现了接口的修改

  继承接口IntefaceA 就必须实现 fun1 方法, 可以选择 是否继承fun2 方法 如ClassB

  然后 接口的引用 可以 调用 fun1 方法 和fun2 方法

  这样我们在修改接口的时候, 就不需要修改 以前的一些类了