0%

lambda 表达式,写法格式是比较固定的。即使我们以最简洁的写法,也是在结构范围内的。但是有一种写法,直接突破了常规的格式,那就是方法引用。相信使用 intellij idea 时,代码提示自动帮你用过这种写法:::,提示是 Replace lambda with method reference

总览

方法引用:简单的说,就是 lambda 表达式的内容,刚好是其他类的某个方法。此时,我们就可以直接引用那个类的那个方法。俗称,处男,哦不,方法引用。

《让子弹飞》一定要申遗

方法引用引用语法常规写法
静态方法引用类名::静态方法(参数) -> 类名.静态方法(参数)
构造方法引用类名::构造方法(参数) -> new 类名(参数)
实例方法引用实例化对象::普通方法(参数) -> 实例化对象.普通方法(参数)
对象方法引用类名::普通方法(实例化对象,参数…) -> 类名.普通方法(参数…)
阅读全文 »

使用函数式接口开发,如果针对每个需要使用的场景都自定义一个函数式接口,会导致我们的项目中有很多仅仅当参数的接口。如果我们能自己抽离这些使用场景的共性,则会省去很多自定义函数式接口,相信很多人会遇到这种情况。幸运的是,JDK 已经提前帮我们把这一步做好了。

Java8 之前的函数式接口

Java8 之前是没有函数式接口这个概念的,但是在 Java8 中,有些接口升级成了函数式接口。最常见的当属以下三位选手:

1 . java.lang.Runnable
2 . java.util.concurrent.Callable
3 . java.util.Comparator

Java8 之后的函数式接口

Java8 提供了一系列的函数式接口,主要在 java.util.function 包目录下。在了解这些函数式接口前,再默念几遍之前反复提到的要点:接口名不重要(反正也是匿名),方法名不重要(反正只有一个抽象方法),重要的是能干什么(行为)

阅读全文 »

前文从策略模式说起,一步一步引出了 lambda 表达式,同时也提到了函数式接口。那么,什么是函数式接口?

什么是函数式接口

函数式接口,就是只有一个抽象方法的接口,可用于 lambda 表达式的接口。

先从 jdk 源码来看,找个大家基本都用过的:Runnable

阅读全文 »

java8 开始,lambda 正式在 JAVA 中出现。有人说它类似于其他函数式编程语言中的闭包,有人说它是一种语法糖。让我们来一步一步了解它。

lambda 表达式的结构

lambda 表达式的结构大致如下,同时遵循偷懒原则:能省则省,能不写就不写。
(类型)(参数1, 参数2, …) -> {方法实现}

  • 类型一般情况下可以自动推导出来,此时可以省略不写。如果存在多个类型满足条件,则需指定类型。
  • 可以有零个或多个参数,参数写在圆括号内。
  • 没有参数时只需写 (),只有一个参数且类型可以推导时可以不写圆括号。
  • 参数的类型可以省略不写,根据上下文来推断。例如:(int a)->{}(a)->{}a->{} 效果相同。
  • 方法实现可以有零条或者多条语句,方法实现写在花括号内。
  • 如果方法实现只有一条语句,则花括号可以省略。如:a -> return a>1
  • 如果方法实现只有一条语句,return 关键字可以省略。如:a -> a==1
  • 如果方法实现有多条语句,则需写在花括号内。
  • 如果方法是静态方法、实例方法或者构造器,可简写。如:(int a) -> {return String.valueOf(a)} 等效于 a -> String.valueOf(a),也等效于 String::valueOf
    阅读全文 »

4年前,在老婆的怂恿下,入手了这款 HHKB。

入手 HHKB

当时原本在用的青轴机械键盘有些按键出了问题送厂返修,修好送回来后,因为青轴的声音在办公室实在太吸引仇恨,所以考虑着换一个键盘。有考虑过换一个红轴或者茶轴,但因 HHKB 的名气、老婆的怂恿、双十一的优惠,最终还是选择了这款退烧神器。

不得不说,这款60键的小键盘还是很有特色的:紧凑的布局,更顺手的 Ctrl,按键分层。当然,因为和标准键盘有差异,这些还是需要花一些时间去适应的,比如无方向键,无F1-F12功能键。

当时用的是还是 windows 的台式机,所以键盘用起来其实还是很方便的。而长期使用之后,也适应了键位的不同,逐渐养成了手感。比如虽然长时间使用了 mbp 的自带键盘,当换上 HHKB 的时候,有些快捷键还是很自然的用了在 windows 下配置的 HHKB 的快捷键。

后来换了 mbp 笔记本,而 HHKB PRO2键盘是有线的。如果键盘放在笔记本上则会因外接线而放不下,而且看起来太丑;如果键盘放在笔记本外,使用触摸板又太不方便。所以就搁置了 HHKB,只使用笔记本的键盘了。

直到前些天,看到了 ydkb 的有线改无线方案,我觉得这款键盘又可以用起来了。

阅读全文 »

距离上次写博客,已过去了有三年。间隔这么久,除了生活上的原因,还离不开自身的懒惰。忽然就想起了 Keep 的 slogan:自律给我自由。可是,拖延才是人的本性。既和人性相悖,自律又从哪里来呢?

生活啊,是不是有点小难?

三年的时间干什么去了

在以前就曾经设想过,如果在同一家公司,能完成结婚、生子、事业,那么,以后这家公司就会在自己回忆中再也避不开了 —— 成家立业。即便是古人,这也是修身之后的奋斗目标了。

不曾想一转眼,自己就完成了半个过程。从为人子,到为人夫,再到为人父,转眼间,孩子都到了事事都会和大人杠的 terrible two 。都说光阴似箭,在匆忙的日子里,更是如此。

你看,这么说来,其实这三年还是发生了很多事的。这些大事中的任何一个,都会让人没了自己的时间。

说起成家,房是一座大山;说起立业,又似乎无所作为。真的是,碌碌无为又一年,年复一年。

写给我的信

阅读全文 »

作为 Java 的关键字,volatile 虽然没有 synchronized 出现的频率高,但是在 Java 源码中还是会经常出现的,尤其是 JUC 当中,比如 AbstractQueuedSynchronizer 。那么,volatile 到底意味着什么,作用是什么?简而言之,有两点,其一是保证了内存可见性,其二是禁止指令重排序。

内存可见性

缓存问题

Java内存模型规定了所有的变量都存储在主内存中,同时每个线程还有自己的工作内存。线程的工作内存中保存了该线程使用到的从主内存拷贝的副本变量,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成。

这样就导致了一个问题:线程1修改了共享变量的值,没来得急写入主存,或者写入主存了线程2并未从主存刷新数据,这样线程2拿到的数据就是过期数据,即内存可见性问题

线程、主内存和工作内存的交互关系如下图所示:

线程缓存

举例

虽说对于可见性问题说的头头是道,但是全是理论。那么怎么证明这个现象的存在呢?看下面的例子。

阅读全文 »

​ 在执行程序时,为了提高性能,编译器和处理器会对指令做一些优化,即指令重排序。但是,重排序也要有一定的标准和依据,否则,就会出现程序不受控制,结果与预期不一致。所以,重排序一定要保证,在重排序后,程序的逻辑不发生改变。保证语义,有 as-if-serial ;保证内存可见性, Java 编程语言规范中,也有 happens-before 规则对其进行限制。

指令重排

经典案例

​ 先从一个经典案例来看下指令重排是否真的存在。

阅读全文 »