月度归档:2019年12月

1. Kotlin hello world!与函数声明

Published / by sickworm / Leave a Comment

首先我们看 Java 的 hello world:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}

非常熟悉。可在我漫长的编程生涯中,我大概是第 5 次在 Google 搜索了“Java Hello world”之后,才能独自完整的默写出来。。因为他有些“不太好记住”的点:比如他必须通过该类的一个叫 main 的 public 的 static 的函数,且这个函数入参必须是有且仅有一个 String[] 数组。如果错了其中一个,那你就没法运行。

这是 Kotlin 版本:

fun main() {
    println("Hello world!")
}

写起来还蛮快乐的,是吧?没有太多多余的东西,很简洁。但大家可能也会有很多疑问。那我们一起来看:

  • Kotlin 的 Hello world 没有声明类。这很不 Java!要知道 Kotlin 或者其他基于 JVM 的语言无论怎么设计,他最终也是要在 JVM 上跑的,而 JVM 恰好就是一套基于类来设计的运行机制,和 Java 的思想是一致的。你 Kotlin 现在自己搞一套,连类都没有了,怎么在 JVM 上跑?

这其实是 Kotlin 编译器的功劳。这点很重要,以后你遇到 Kotlin 的新特性,和 Java 对不上的时候,就回想这点:都是 Kotlin 编译器的功劳,他把 Kotlin 代码转换成了符合 Java 思想的 JVM 字节码。小本本记好啦,这句话将贯穿整个 Kotlin 学习。

如果你用过 jadx的话,可以反编译试试。这里的结论就是:HelloWorld.kt 会被编译为一个叫 HelloWorkKt 的类,把这段代码塞进去。当然你再去创建一个 HelloWorldKt 的类就会报错了,你可以试试 🙂

  • 没有分号。古时候,一行完整的代码用分号来分隔。后来大家觉得分号已经没有必要了,也基本没有人会在一行写几行代码了。新的语言一部分是柔和派,分号变为可选;另一部分激进派直接去掉了分号。Kotlin 属于前者,如果你写一个分号,IDE 爸爸会告诉你,没得必要,但不会报错。如果你故意把两行代码写成一行,中间加一个分号,这个分号就是必要的。

  • 函数的声明通过 fun 关键字。欸?Java 不需要关键字来声明函数呀。以 JavaScript 为首的语言认为,函数是一等公民,应当做一个对象看待。这样函数就可以被持有,被传递,提高他的灵活性。所以像 JavaScript 这样的语言,方法声明会有关键字,否则你就不知道自己到底是在调用一个函数,还是在执行一个变量持有的函数了。

Kotlin 也支持函数是一等公民,所以函数声明需要关键字。Java 其实也有类似的东西,他叫匿名类。只不过匿名类需要声明一个类,再用匿名类的特殊写法去创建一个看起来像函数对象的东西。

  • 函数属性默认是 public。 Java 默认是用的很少的 package private。
  • 函数默认返回值是 Unit。 Java 没有默认返回值,需要显式声明为 void。为啥 Kotlin 不用 void 呢?因为声明返回值为 Unit 可以让一切对象化,在某些场景可以简化代码编写。举一个简单的情况,你可以写 return println("Hello world!"),而不再需要写成两行了。

  • **println 代替了 System.out.println **。学 Java 的时候大家应该都吐槽过,写个打印好废键盘啊!这是因为 Java 严格按照对象调用的规则办事,方法必须是属于类的,除非你在类里面调同一个类里的办法,可以省略this.,其他地方都需要加对象才能调用一个方法(类也是对象嘛)。

所以 Kotlin 是怎么做到不用指定对象也能调用方法呢?是有顶层声明(top-level declaration)的特性。就像第一点提到的那样,Kotlin 编译器会通过各种各样的方法把顶层声明的函数编译成对象方法调用的形式。顶层声明还有更多酷炫的能力,比如给任意一个类“增加方法”,后面我们会展开来讲。

以上就是 Kotlin 的 Hello world 涉及到的几个知识点。是不是觉得要写个 Hello world 也要懂这么多很费劲呢?其实要弄懂 Java 的 Hello world 也很费劲的,只是你已经过去那个初学的阶段了。在 Java 的基础上理解 Kotlin 相对还是简单的,如果你有其他语言的开发经验那就更简单了,因为 Kotlin 的特性,基本都能在某个语言上找到,它本身并不是新特性的创造者,他只是好用特性的搬运工。

版权所有,转载请注明出处:
https://sickworm.com/?p=1768

0. 如何判断一门语言的好坏

Published / by sickworm / Leave a Comment

我在组内推广 Kotlin 遇到不少挑战,虽然我自己觉得它确实是一门优秀的语言,有着丰富的特性,能提高我们开发效率,减少 bug 的出现,但同事们并不觉得。而且他们的观点往往不是“Kotlin 并没有比 Java 好多少”,而是“Kotlin 就没比 Java 好“。Kotlin 语法不习惯;Kotlin 这样强推这么多年,也不温不火,说明 Kotlin 不行。

所以本着“先问是不是,再问为什么”的原则,我们在讨论“Kotlin 比 Java 好在哪里之前”,必须先说清楚“Kotlin 比 Java 好吗”这个问题。

关于判断语言是否优秀,我们听过最多的可能就是“XXX 是最好的语言”了。不过这种旧世界的观点,在大家充分学习了网络上的编程知识之后,现在都成为大家调侃的段子了。现在,我们更喜欢“编程语言没有优劣之分”,“没有最好的编程语言,只有最适合的应用场景”这样的论调。这听起来就很有哲理,很编程正确嘛!如果把这些的观点套在 Java 和 Kotlin 身上,也可以得到“要根据具体场景,有些场景确实 Java 更好”的观点。

不过今天,我们不谈这些和稀泥的观点。这篇文章会告诉大家,客观准确评判一门语言好坏的标准。

无论如何,编程语言是给人使用的,那我们就从人本身特点出来来讲这个逻辑。我们人是靠大脑思考的,而大脑有个致命的缺点:容量有限,且有一定错误率。这就导致我们程序员在编写状态复杂流程冗长的代码的时候,容易出现错误。这是人大脑的特点决定的,无法避免。

但劳动人民的智慧是无穷的,程序员们想出各种办法来降低自己犯错概率。从机器码到汇编,到面向流程,到面向对象,到设计模式,编码规范,高级语法特性,不断有新编程技术的出现,让程序员们可以写更简单的代码。也就是用更抽象的表达来表示同样的意图

阿拉伯人:30 加 42 等于 72。

法国人: 30 加 40又2 等于 60又10又2。

你能想象,用汇编去实现你现在要的一个业务,需要多长时间?写出来会有多少个 bug 吗?当你用 Python 快速实现了一个算法并开始验证的时候,别人可能还在用 C++ 吭哧吭哧地写着 std::vector 的 for 循环;当你用 Swift 快速实现了一个 iOS demo 的时候, 别人可能还在用 objective-C 吭哧吭哧的写着头文件声明;当你用 Go 的协程快速实现了并发处理时,别人可能还在用 Java 吭哧吭哧地实现一个线程池。又或者说,用 C++ 和 Java 实现同一个需求,C++ 你需要花费额外的精力关注内存管理,数组越界,类型安全等问题,这样你留给业务本身的精力就少了,开发变慢了,bug 也更容易出现了。

Java:你知道单例线程安全的四种写法吗?

Kotlin:你是说 by lazy 吗?

编程语言是为了实现业务而存在的,那我们就应该选择一门实现业务编写效率高,维护成本低的编程语言。

编写效率高意味着同样的功能我可以用更少的代码实现;同时 sdk 功能齐全,轮子多,大部分基础组件不需要重复开发。没错就像 Python 那样。Kotlin 相比 Java,他的语法表达更简洁,更容易写出低耦合,高内聚的代码;且和 Java 互操作的特性,可以直接使用 Java 的轮子,大大缩短了建设 Kotlin 生态的过程。

维护成本低分为几个方面,分别是:bug 少,代码简洁易懂,对需求变更友善。

bug 少。国外有对千行 bug 数量进行了研究,研究提出 bug 数量和所使用的语言没有直接关系,和语法表达流畅性有关系^[https://stackoverflow.com/questions/2898571/basis-for-claim-that-the-number-of-bugs-per-line-of-code-is-constant-regardless], ^[https://stackoverflow.com/questions/2898571/basis-for-claim-that-the-number-of-bugs-per-line-of-code-is-constant-regardless]。 我觉得可以理解为,人大脑的犯错频率是比较固定的,使用时长越长,出现的“bug”也就越多。如果你能通过选择一门语言,更快的实现指定功能,那么 bug 数量会相应减少。

代码简洁易懂。Kotlin 需要编写的代码更少,是因为 Kotlin 对语意有更精简的表达,你在习惯之后可以比 Java 更快的阅读完同样的功能。这点在后面我会继续说明。

对需求变更友善。这是代码简洁易懂的自然延伸,所谓 less is more 嘛。

Pythonista:人生苦短,我用 Python。

Androider:以前我没得选,现在我想做个 Kotlin boy。

PS:我也了解到很多同学拒绝 Kotlin 的理由是“不习惯”。比如说语法用着不习惯,看着也不习惯,很难看懂云云。我想说的是,无论是编程语言还是其他工作外的事,千万要忌讳用“习惯”作为理由。那些 30 多岁的外企程序员,失业中年危机,不就是“习惯”习出来的么?习惯会让你避开新的东西,而能让你能力,事业,资产产生“增量”的,往往就是这些新的东西。新的东西最容易产生“增量”。

我们判断一个东西好不好,有没有价值,有没有必要去投入,不要用“习惯”。要把好与不好列出来。就像我这样,我说 Kotlin 好,我把好的理由讲给你听,你觉得没道理,你可以针对这些点进行反驳,或者提出新的观点,然后和我进行讨论。用“不习惯”作为理由来拒绝,只会让自己错失“增量”的机会。

版权所有,转载请注明出处:
https://sickworm.com/?p=1766

Kotlin 从拒绝到真香

Published / by sickworm / Leave a Comment

《Kotlin 从拒绝到真香》是一系列介绍 Kotlin 好用的特性的文章。文章会以某一个经典的 Java 使用场景开始,提供相应的 Kotlin 实现代码,并讲解其中用到的特性。

文章主要面向 Android 开发者。如果你正在考虑是否使用 Kotlin 来代替 Java 作为 Android 开发语言,这些文章会非常适合你。笔者所在团队正积极使用 Kotlin,并有计划的使用 Kotlin 重构项目代码。但对团队成员来说,使用 Kotlin 并不是强制的。笔者团队内推广 Kotlin 的过程中也遇到了部分同事“拒绝”Kotlin,而这些文章正是我在推广和不断尝试说服他们的过程中逐渐积累起来的“真香”部分。

文章不求鞭辟入里,但尽可能保证有趣不枯燥。如果恰好你也喜欢这些文章,请务必 star 它!

作为 Android 开发者的你肯定已经拥有了 Android Studio,但我还是建议你下载一个 JetBains CE 或其他版本,这样你可以方便的创建一个 Kotlin 文件并运行它。大部分例子中,我们只需要 kotlin 的环境就可以了。
https://play.kotlinlang.org 是一个在线 Kotlin playground,使用它可以方便快速的运行一小段代码。

版权所有,转载请注明出处:
https://sickworm.com/?p=1760