閱讀Kotlin Programming一書的筆記

最近在Safari Book Online上閱讀Big Nerd Ranch Guide的Kotlin Programming一書。此書寫得非常精彩,雖然是從最基礎(chǔ)的語法開始交起,對于我這個有著十載編程經(jīng)驗的人,依然很有收獲。由于Kotlin的知識點非常多,大腦無法在短時間沒有實作的鞏固下牢記。所以留以此文已備參考。

第一章:Your First Kotlin Application

首先JetBrains出產(chǎn)的IntelliJ IDEA是編寫Kotlin程序不二的選擇。為什么?

IntelliJ IDEA, called IntelliJ for short, helps you write well-formed Kotlin code. It also streamlines the development process with built-in tools for running, debugging, inspecting, and refactoring your code.

IntelliJ的項目

A project includes all of the source code for your program, along with information about dependencies and configurations. A project can be broken down into one or more modules, which are like subprojects. By default, a new project has one module, which is all you need for your simple first project.

Sandbox項目的結(jié)構(gòu)

項目結(jié)構(gòu)

The Sandbox.iml file contains configuration information specific to your single module. The .idea folder contains settings files for the entire project as well as those specific to your interaction with the project in the IDE (for example, which files you have open in the editor). Leave these auto-generated files as they are.

Sandbox.iml文件是針對單個模塊的,包含該模塊配置信息。.idea文件夾包含整個項目的設(shè)置和你與項目在IDE中交互設(shè)置文件。

The External Libraries entry contains information about libraries the project depends on. If you expand this entry you will see that IntelliJ automatically added Java 1.8 and KotlinJavaRuntime as dependencies for your project.

接下來是教授任何一門新語言的第一個程序:Hello World程序。創(chuàng)建Hello.kt并鍵入:

fun main(args: Array<String>) {
    println("Hello, world!")
}

注意:IntelliJ提供了一個編寫main函數(shù)樁代碼的快捷方式,輸入單詞main然后按下Tab鍵。

相比Java,Kotlin做最簡單的事情,也比Java簡單很多,不再像“萬物皆對象”那樣,為一個簡單的Hello World程序也要創(chuàng)建一個類,把函數(shù)包進(jìn)類定義中。Kotlin也不再稱main為方法(method),而是函數(shù)(function)。

This particular function – the main function indicates the starting place for your program. This is called the application entry point, and one such entry point must be defined for any program to be runnable.

println()Kotlin標(biāo)準(zhǔn)庫(Kotlin standard library)的一個內(nèi)建函數(shù)。

Kotlin/JVM代碼的編譯與執(zhí)行

按下運行HelloKt按鈕知道控制臺輸出Hello, World!之間,幕后發(fā)生了很多事。

First, IntelliJ compiles the Kotlin code using the kotlinc-jvm compiler. This means IntelliJ translates the Kotlin code you wrote into bytecode, the language the JVM “speaks.” If kotlinc-jvm has any problems translating your Kotlin code, it will display an error message (or messages) giving you a hint about how to fix the issues. Otherwise, if the compilation process goes smoothly, IntelliJ moves on to the execution phase.

In the execution phase, the bytecode that was generated by kotlinc-jvm is executed on the JVM. The console displays any output from your program, such as printing the text you specified in your call to the println() function, as the JVM executes the instructions.

When there are no more bytecode instructions to execute, the JVM terminates. IntelliJ shows the termination status in the console, letting you know whether execution finished successfully or with an error code.

The Kotlin REPL

Kotlin REPL的話,目前還很難感知它的實用性,不過記住它的入口是Tools->Kotlin->Kotlin REPL,還有記住在REPL中evaluate代碼的快捷鍵:Command-Return (Ctrl-Return)

For the More Curious: Why Use IntelliJ?

曾記得十年前初學(xué)Java時,我是習(xí)慣使用普通的文本編輯器(EditPlus)編寫Java示例代碼的。Kotlin當(dāng)然也可以使用text editor編寫,但是此書作者建議初學(xué)者使用IntelliJ。如此來看,Kotlin淪陷為最好在IDE中編寫程序的語言了。確實IntelliJ非常的智能,程序員仰賴IntelliJ對代碼進(jìn)行的細(xì)致的檢測以寫出語法正確的代碼。正如該節(jié)末尾所指出的:

Also, since Kotlin was created by JetBrains, the integration between IntelliJ and Kotlin is carefully designed – often leading to a delightful editing experience.

For the More Curious: Targeting the JVM

The JVM is a piece of software that knows how to execute a set of instructions, called bytecode. “Targeting the JVM” means compiling, or translating, your Kotlin source code into Java bytecode, with the intention of running that bytecode on the JVM.

編譯與執(zhí)行流程

Since Kotlin can be converted to bytecode that the JVM can execute, it is considered a JVM language. Java is perhaps the most well-known JVM language, because it was the first. However, other JVM languages, such as Scala and Kotlin, have emerged to address some shortcomings of Java from the developer perspective.

Kotlin is not limited to the JVM, however. At the time of this writing, Kotlin can also be compiled into JavaScript or even into native binaries that run directly on a given platform – such as Windows, Linux, and macOS – negating the need for a virtual machine layer.

第二章:變量、常量和類型(Types)

Types describe the particular kind of data that is held by a constant or variable.

變量和常量有一個指定的數(shù)據(jù)類型,告訴了編譯器如何處理type checking

type checking will be handled, a feature in Kotlin that prevents the assignment of the wrong kind of data to a variable or constant.

聲明一個變量

Kotlin使用var來聲明變量,如果編譯器能夠推斷出變量的具體類型,那么類型就可以不用聲明。比如:

fun main(args: Array<String>) {
    var experiencePoints: Int = 5
    println(experiencePoints)
}

也可以簡化成:

fun main(args: Array<String>) {
    var experiencePoints = 5
    println(experiencePoints)
}

似乎IntelliJ并不鼓勵在可以推斷類型的情況下顯示聲明類型。

變量聲明剖析圖

Kotlin uses a static type system – meaning the compiler labels the source code you define with types so that it can ensure the code you wrote is valid. IntelliJ also checks code as you type it and notices when an instance of a particular type is incorrectly assigned to a variable of a different type. This feature is called static type checking, and it tells you about programming mistakes before you even compile the program.

Kotlin's Built-in Types

Kotlin的內(nèi)建數(shù)據(jù)類型有String, Char, Boolean, Int, Double, List, Set, Map,雖然這些類型在Java中也有,但是要記住這些是Kotlin自己定義的類型。

Read-only Variables只讀變量

You declare a variable that can be modified using the var keyword. To declare a read-only variable, you use the val keyword.

var關(guān)鍵字的引入,就我來看,是起到強(qiáng)促程序員多多使用常量。就像作者所說:

...we recommend that you use a val any time you do not need a var.

image

IntelliJ can detect when a var can be made a val instead by analyzing your code statically. If a var is never changed, IntelliJ will suggest that you convert it to a val.

To apply the suggestion, click on the var keyword next to playerName and press Option-Return (Alt-Enter). In the pop-up, select Make variable immutable

Type inference

Kotlin includes a feature called type inference that allows you to omit the type definition for variables that are assigned a value when they are declared.

Note that IntelliJ will display the type of any variable on request, including those that use type inference. If you ever have a question about the type of a variable, click on its name and press Control-Shift-P. IntelliJ will display its type.

image

Compile-Time Constants

val聲明的數(shù)據(jù)并不一定是不可改變的常量,如果要讓數(shù)據(jù)絕對不可變,要考慮用編譯時常量

A compile-time constant must be defined outside of any function, including main, because its value must be assigned at compile time (that is, when the program compiles) – hence the name. main and your other functions are called during runtime (when the program is executed), and the variables within them are assigned their values then. A compile-time constant exists before any of these assignments take place.

Compile-time constants also must be of one of the basic types(String, Int, Double, Float, Long, Short, Byte, Char, Boolean), because use of more complex types for a constant could jeopardize the compile-time guarantee.

const val MAX_EXPERIENCE: Int = 5000

fun main(args: Array<String>) {
    ...
}

這里定義的變量并不是local to a function or class – a file-level variable

Prepending a val with the const modifier tells the compiler that it can be sure that this val will never change. In this case, MAX_EXPERIENCE is guaranteed to have the integer value 5000, no matter what. This gives the compiler the flexibility to perform optimization behind the scenes.

Inspecting Kotlin Bytecode

Kotlin is an alternative to Java for writing programs that run on the JVM, where Java bytecode is executed. It is often useful to inspect the Java bytecode that the Kotlin compiler generates to run on the JVM. You will look at the bytecode in several places in this book as a way to analyze how a particular language feature works on the JVM.

Knowing how to inspect the Java equivalent of the Kotlin code you write is a great technique for understanding how Kotlin works, especially if you have Java experience.

For the More Curious: Java Primitive Types in Kotlin

Java中有Primitive類型和Reference類型。引入Primitive Types是出于性能考量:實例化開銷、內(nèi)存占用都會小很多...;Kotlin僅提供一種數(shù)據(jù)類型:Reference類型。

Kotlin made this design decision for several reasons. First, if there is no choice between kinds of types, you cannot code yourself into a corner as easily as you can with multiple kinds to choose from. For example, what if you define an instance of a primitive type, then realize later that you need to use the generic feature, which requires a reference type? Having only reference types in Kotlin means that you will never encounter this problem.

Kotlin編譯器會將可以轉(zhuǎn)換為Primitive類型的應(yīng)用類型轉(zhuǎn)換為Primitive類型

 var experiencePoints: Int = 5

會被轉(zhuǎn)換成

int experiencePoints = 5;

Kotlin gives you the ease of reference types with the performance of primitives under the hood. In Kotlin you will find a corresponding reference type for the eight primitive types you may be familiar with in Java.

第三章:Conditionals

==在Kotlin中是結(jié)構(gòu)相等操作符(Structural equality operator),被讀作“相等”。

Using the addition operator (+) to append a value to a string is called string concatenation. It is an easy way to customize what is printed to the console based on the value of a variable.
+運算符在字符串上被重載為字符串拼接操作,Kotlin推薦使用String templating來把值注入到字符串內(nèi)。

Ranges

雖然Java中也可以寫一個自定義的Range類來支持表示“范圍”的概念,但是Kotlin是從語言級別上支持這個概念。如果不是從語言級別上支持的話,任何的模仿只是拙劣的模仿。

Kotlin provides ranges to represent a linear series of values.

In addition to the .. operator, several functions exist for creating ranges. The downTo function creates a range that descends rather than ascends, for example. And the until function creates a range that excludes the upper bound of the range specified.

... use the in keyword to check whether a value is within a range...

when表達(dá)式

竊以為,when是Kotlin作者對Java中的switch的改進(jìn)。

By default, a when expression behaves as though there were a == equality operator between the argument you provide in parentheses and the conditions you specify in the curly braces.

val healthStatus = when (healthPoints) {
    100 -> "is in excellent condition!"
    in 90..99 -> "has a few scratches."
    in 75..89 -> if (isBlessed) {
        "has some minor wounds but is healing quite quickly!"
    } else {
        "has some minor wounds."
    }
    in 15..74 -> "looks pretty hurt."
    else -> "is in awful condition!"
}

String Templates字符串模板

Kotlin features string templates to aid in this common need and, again, make your code more readable. Templates allow you to include the value of a variable inside a string’s quotation marks.

$ symbol indicates to Kotlin that you would like to template a val or var within a string you define, and it is provided as a convenience.

Kotlin also allows you to evaluate an expression within a string and interpolate the result – that is, to insert the result into the string. Any expression that you add within the curly braces after a dollar-sign character (${}) will be evaluated as a part of the string.

println("(Aura: $auraColor) (Blessed: ${if (isBlessed) "YES" else "NO"})")
println("$name $healthStatus")

第四章:函數(shù)
把重復(fù)執(zhí)行的語句提取并重構(gòu)成方法是IntelliJ提供的便利:

Control-click (right-click) on the code you selected and choose Refactor → Extract → Function…

提取方法

Anatomy of a Function

方法由頭和體組成
方法頭剖析

A function can optionally begin with a visibility modifier. The visibility modifier determines which other functions can “see” – and therefore use – the function.

By default, a function’s visibility is public – meaning that all other functions (including functions defined in other files) can use the function. In other words, if you do not specify a modifier for the function, the function is considered public.

For each parameter, the definition also specifies the type of data it requires.
在方法頭,參數(shù)的定義是必須指定數(shù)據(jù)類型的,不可以依賴類型推斷。

Note that function parameters are always read-only – they do not support reassignment within the function body. In other words, within the body of a function, a function parameter is a val, instead of a var.

The file-level variable can be accessed from anywhere in the project (though a visibility modifier can be added to the declaration to change its visibility level). File-level variables remain initialized until program execution stops.

Because of the differences between local and file-level variables, the compiler enforces different requirements on when they must be assigned an initial value, or initialized.

File-level variables must always be assigned when they are defined, or the code will not compile. This requirement protects you from unexpected – and unwanted – behavior, like a variable not having a value when you try to use it.

Since a local variable is more limited in where it can be used – within the scope of the function in which it is defined – the compiler is more lenient about when it must be initialized. A local variable only has to be initialized before it is used.

Default Arguments默認(rèn)實參

...you can assign a default value for a parameter that will be assigned if no argument is specified.

private fun castFireball(numFireballs: Int = 2) {
    println("A glass of Fireball springs into existence. (x$numFireballs)")
}
castFireball(5)
castFireball()

Single-Expression Functions

For single-expression functions, you can omit the return type, curly braces, and return statement.

private fun castFireball(numFireballs: Int = 2) =
    println("A glass of Fireball springs into existence. (x$numFireballs)")

Notice that instead of using the function body to specify the work the function will perform, with single-expression function syntax you use the assignment operator (=), followed by the expression.

Unit Functions

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內(nèi)容