这题我来,顺便复习一下java的lambda表达式。
Java8 推出了属于Java的lambda表达式,与一众的 => 不同,Java选择了 -> 做为箭头符号。有没有观众知道为什么这么选择。 lambda表达式的基本格式是这样的具体是什么意思呢,这里就要提一下使用lambda表达式的前提了。
<hr/>labmda表达式一般用来实现一个函数式接口。
比如java.lang.Iterable 的 foreach(xxx)方法中的xxx位置需要一个 Consumer 接口类- default void forEach(Consumer<? super T> action) {
- Objects.requireNonNull(action);
- for (T t : this) {
- action.accept(t);
- }
- }
复制代码 而 Consumer 正好是一个函数式接口,@FunctionalInterface 注解了解一下。- @FunctionalInterface
- public interface Consumer<T> {
- ...
- void accept(T t);
- ...
- }
复制代码 这时候可以这么用 Consumer one = (x) -> { System.out.println(x) } ,这句可以和上面结合起来看,x就是accept中的t,花括号里没有return是因为accept返回值是void。因为 Consumer 接口中只有一个方法,因此不会有冲突的可能。 然后再把 one 传进去forEach就可以了。
<hr/>赋值后,也可以直接调用接口中的方法。相似的,我们也可以自己写一个函数式接口。
- interface Person{
- void say(String t);
- }
- class AnimalSay{
- public static void saySomething(String something,Person person) {
- person.say(something);
- }
- }
- public class Mian {
- public static void main(String[] args) {
- Person xiaoMing = (x) -> { System.out.println(x); }; //1
- //xiaoMing.say(&#34;hello&#34;);
- AnimalSay.saySomething(&#34;hello&#34;, xiaoMing ); //2
- //AnimalSay.saySomething(&#34;hello&#34;, (x)->{System.out.println(x)};); //3
- }
- }
复制代码 可以直接把 lambda 表达式直接放在需要的位置。这时候 lambda 就可以自动变成所需类 (上面代码被注掉的部分)。
那么回到最开始也有两种用法- //第一种
- Consumer one = (x) -> { System.out.println(x);};
- Iterable.foreach(one);
- //第二种
- Iterable.foreach( x->System.out.println(x) );
复制代码 <hr/>那么双冒号是什么意思?
lambda 表达式允许4种方式的双冒号
其中的 Class 指的是类名,产生于 class Class { }。object 是实例对象,产生于 Class object = new Class(); 一个一个的说。
object::instanceMethod 的一个典型用法就是 System.out::println out继承于FilterOutputStream,可以看成System的一个成员对象,通过它可以调用printstream中的输出方法。 System.out是printStream的实例: 因为System类当中的out 数据成员是由printStream流创建出来的对象,在system类中为public static final printStream out 而且out又是static的,所以只能够通过system来调用,即为System.out了。System.out说是printStream的实例化对象,意思就是说System类当中的out数据成员即为printStream 类的对象了。System.out 整个就表示屏幕输出了,这时候还只是字节流而已,当调用pringStream的方法println()是就表示用什么用的方式打印输出的关系了。 在此请回看 Consumer 类的代码,就明白了为什么 ```Consumer one = System.out::println``` 是 ```Consumer one = t -> System.out.println(t)``` 的简写
在这里插一个多线程的lambda表达式使用技巧:- public class SynchronizedTest {
- public synchronized void method1() {
- System.out.println(&#34;Method 1 start&#34;);
- try {
- System.out.println(&#34;Method 1 execute&#34;);
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(&#34;Method 1 end&#34;);
- }
- public synchronized void method2() {
- System.out.println(&#34;Method 2 start&#34;);
- try {
- System.out.println(&#34;Method 2 execute&#34;);
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(&#34;Method 2 end&#34;);
- }
- public static void main(String[] args) {
- // 一种最简洁的启动方法
- // new Thread( ()-> new SynchronizedTest().method1() ).start();
- //新建实例对象的启动方法
- final SynchronizedTest test = new SynchronizedTest();
- new Thread(test::method1).start();
- new Thread( ()-> test.method1() ).start();
- //显式的赋值Runnable后再启动
- Runnable tt = test::method1;
- new Thread(tt).start();
- //
- new Thread(test::method2).start();
- //运行完后对结果有没有疑问? 为什么2后面还有1?
- }
- }
复制代码 |