Scala 自身类型(self-type) 解析

Scala 有一个自身类型(self-type) 的东西,由来已久,居然今天才发现。如果一个类或 trait 指明了 self-type 类型(包括类和特质),它的子类型或是对象也必须是相应的类型。它产生的效果与继承(或 mixin) 颇有几分相似。self-type 的语法是 this 的别名: 某一类型(class 或 trait), 直接看一个例子:

上面 this: User => 中的 this 只是一个别名,可以是 self 或任何有效标识(如  abc: User),这里使用 this 等于未指定别名,与原本的 this 重叠了。如果声明为非 this 的话则可以这么用 阅读全文 >>

Akka Actor: 从最简单的例子开始

Akka 是什么?它提供了 JVM 上的 Actor 编程模型 -- 同时兼顾了并发与分布式。它由 Scala 编写的,替代了 Scala 本身的 Actor。Actor 视线程为重量级的资源,能够以少量的内存胜任更高的并发,类似的东西有纤程,协程。有一个数据对比是同样的 1GB 内存,可以创建 2.7M 个 Actor, 而线程只能创建 4096 个,仅供参考,当然 Java 也是会基于线程池来执行的。

Actor 增加了程序的灵活性,并减轻了复杂度(标准的赞美之辞)。

所谓 Action 编程模型兼顾并发与分布,是由于让你编程时可以不用考虑线程,线程配置成为部署的范畴; Actor 之间通信只能发送异步消息,Actor 可以分布在同一 JVM, 不同 JVM, 或是不同物理机器上。

因为 《Akka IN ACTION》中提供了第一个例子起点着实有点高,所以网上找来了一个了解 Akka Actor 的最简单例子,来自于 Simple Scala Akka Actor examples (Hello, world examples)。并非纯属翻译,主要是为了练手,所以不完全一致: 阅读全文 >>

并发(Concurrent) 与并行(Parallel) 的区别

刚开始阅读 《Akka IN ACTION》这本书,刚开始是对 Revolution 这个词翻译成中文是革命 感到诧异,因为革命 通俗来讲就是 杀人 的意思。至于 Revolution 英文解释不深究了,只是感叹何以颠覆性的变化就一定要杀人吗?

也由此引出了编程中经常面对的 Concurrent(名词为:Concurrency) 和 Parallel(名词为:Parallelism) 这两个词,基本上是认为它们是同一个意思。其实不然,下面慢慢道来。

如果从英文字典对它们的解释也没有多大区别,差不多都是说同是发生,但字面上 Parallel 多了一个平行的意思。所以在中文上,在计算机领域我们约定的翻译是

  • Concurrent(Concurrency)  --  并发
  • Parallel(Parallelism)           --  并行

比如在多线程环境中它们的区别具体体现在:

并发:多个任务在同一个 CPU 核上按细分的时间片轮流(交替)执行,从逻辑上来看那些任务是同时执行。针对 CPU 内核来说,任务仍然是按细粒度的串行执行。也难怪在 Java 5 中新加的并发 API 的包名是 java.uti.concurrent阅读全文 >>

Java 8 根据属性值对列表去重

对列表的去重处理,Java 8 在 Stream 接口上提供了类似于 SQL 语句那样的 distinct() 方法,不过它也只能基于对象整体比较来去重,即通过 equals/hashCode 方法。distinct 方法的功效与以往的 new ArrayList(new HashSet(books)) 差不多。用起来是

List<Book> unique = book.stream().distinct().collect(Collectors.toList())

并且这种去重方式需要在模型类中同时实现 equals 和 hashCode 方法。

回到实际项目中来,我们很多时候的需求是要根据对象的某个属性来去重。比如接下来的一个实例,一个 books 列表中存在 ID 一样,name 却不同的 book, 我们认为这是重复的,所以需要根据 book 的 id 属性对行去重。在 collect 的时候用到的方法是 collectinAndThen(...), 下面是简单代码: 阅读全文 >>

JVM 上的 Lisp 方言 Clojure 1.9

还是从 OSChina 网站上得知 Clojure 1.9 在  2017 年 12 月发布的,时值这么久才开始真正去了解一下这个新版本。距离上一个版本 1.8 的发布时间(2016 年 1  月), 大概两年才出一个版本,而且总的说来 Clojure 1.9 并没有带来多大惊喜。

唯一能带来点喜气的也就是 Clolure 有了自己的命令行工具了,再也无需寄身于 Leiningen(一个 Clojure 构建工具,相当于 sbt 之于 Scala) 的篱笆之下了。以 Mac OS 平台为例,以前试图用 brew 来直接安装 clojure 的时候会提示找不到 clojure, 建议安装 leiningen.

$ brew install clojure

在 Clojure 1.9 出来之前,上面的命令会得到如下提示信息

Error: No available formula with the name "clojure"
Clojure isn't really a program but a library managed as part of a
project and Leiningen is the user interface to that library.
To install Clojure you should install Leiningen:
brew install leiningen
and then follow the tutorial:
https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md

所以那时候不得不用 阅读全文 >>

使用 Mockito 的 @InjectMocks 创建被测试类实例

初识 Mockito 这个测试框架后,我们要使用 Mock 的属性创建一个被测试类实例时,大概会下面这么纯手工来打造。

假定类 UserService 有一个属性 UserDao userDao, 需要构造 UserService 实例时 Mock 内部状态

UserDao userDao = Mockito.mock(UserDao.class);
UserService testMe = new UserService(userDao);

如此,userDao 的行为就可以自由模拟了,这种纯手工方式都不需要给测试类添加

@RunWith(MockitoJunitRuner.class)
//或
MockitoAnnotations.initMocks(this);

因为上面两句是给 Mockito 的注解使用的。

如果所有的 Mock 对象全部通过手工来创建,那就不容易体现出 Mockito 的优越性出来。因此对于被测试对象的创建,Mock 属性的注入应该让 @Mock 和 @InjectMocks 这两个注解大显身手了。

标注在实例变量上的 @Mock 相当于是 Mockito.mock(Class) 创建了一个 Mock 对象,而 @InjectMock 标的实例会寻找到相应 Mock 属性想法构造出被测试类的实例。看下面的例子: 阅读全文 >>