官網 referencejava
kotlin實戰mysql
Try Kotlingit
Kotlin Chinagithub
Githubweb
Kotlin是一門把Java平臺做爲目標的新的編程語言。它簡潔、安全、優雅並且專一於和Java代碼間的互操做性。它幾乎能夠用於現在Java遍佈的全部地方.spring
- Kotlin是靜態類型的,支持類型推斷的,在保持代碼精簡的同時維持準確性和性能。
- kotlin同時支持面向對象和函數式編程風格,經過把函數放在一等公民的位置實現更高層次的抽象,經過支持不可變值簡化了測試和多線程開發。
- Kotlin在服務器端應用運行良好。它能全面支持現有的Java框架併爲公共任務提供了新的工具,例如生成HTML和保持一致性。
- Kotlin是免費和開源的。它爲主流IDE和構建系統提供了全面的支持。
- Kotlin是優雅的、安全的、精簡的以及互操做性強的(語言)。這意味着它專一於使用已經被證實的方案來解決常見任務,阻止通常的錯誤,例如:NullPointerException,支持緊湊和易讀的代碼,鬆散的Java集成功能。
kotlin構建流程:
sql
fun main(args: Array<String>) { println("Hello, world!") }
函數聲明以fun關鍵字爲開始,接着是函數名:max。接着是圓括號中的參數列表。返回類型跟在參數列表後面,以冒號分隔。數據庫
在kotlin中if是一個表達式; if的分支能夠是代碼塊, 代碼塊中最後的表達式就是這個代碼塊的值; 若是if被用做表達式(好比返回值或者給變量賦值), 則須要有else分支.express
若是函數的內容部分只有一個表達式,你能夠移除大括號和return聲明,使用表達式做爲整個函數的主體;對於表達式主體函數來講,編譯器可以分析用作主函數主體的表達式,並使用表達式的類型做爲函數返回類型.只有表達式函數才容許忽略返回值。編程
fun max(a: Int, b: Int) = if (a > b) a else b
定義參數時,默認參數值能夠減小函數的重載:
fun <T> joinToString( collection: Collection<T>, separator: String = ", ", prefix: String = "", postfix: String = "" ): String
調用Kotlin中定義的函數時, 能夠指定參數的名稱, 使代碼更易讀, 但調用Java中的方法並不行:
// 有默認參數值的參數可省略 joinToString(collection = collection, postfix = " ")
有兩個關鍵詞來聲明一個變量:
若是變量有初始化器, 能夠忽略變量的類型聲明:
val message = "Success"
final String message = "Success";
一個val變量必須在定義塊執行時被初始化並且只能一次。若是編譯器可以確保惟一的初始化聲明可以其中一個被執行, 你能夠根據狀況用不一樣的值初始化變量:
val message: String if ( canPerformOperation()) { message = "Success" } else { message = "Failed" }
字符串能夠包含模板表達式, 即一些小段代碼, 會求值並把結果合併到字符串中.
val s = "abc" val str = "$s.length is ${s.length}" // "abc.length is 3" val price = """ ${'$'}9.99 """
聲明一個有name屬性的類:
class Person(val name: String)
在Java中:
public class Person{ private String name; public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
在Kotlin中的一個類能夠有一個主構造函數和一個或多個次構造函數.主構造函數是類頭的一部分: 它跟在類名(和可選的類型參數)後
class Person(firstName: String) { }
若是主構造函數沒有任何註解或者可見性修飾符, 能夠省略這個 constructor
關鍵字.
class Person(firstName: String) { }
主構造函數不能包含任何的代碼. 初始化的代碼能夠放到以 init 關鍵字做爲前綴的初始化塊中:
class Customer(name: String) { val customerKey = name.toUpperCase() init { logger.info("Customer initialized with value ${name}") } }
class Person(val firstName: String, val lastName: String, var age: Int) { // …… }
聲明次構造函數
class Person { constructor(parent: Person) { parent.children.add(this) } }
若是類有一個主構造函數, 每一個次構造函數須要委託給主構造函數, 能夠直接委託或者經過別的次構造函數間接委託:
class Person(val name: String) { constructor(name: String, parent: Person) : this(name) { parent.children.add(this) } }
聲明屬性的完整語法:
var <propertyName>[: <PropertyType>] [= <property_initializer>] [<getter>] [<setter>]
kotlin中,類沒有字段。
class Person( val name: String, // 只讀屬性,生成一個幕後字段和一個簡單的getter var isMarried: Boolean // 可寫屬性,生成一個幕後字段和簡單的getter和setter )
若是屬性的名稱以"is"開頭,那麼它的getter不會增長任何前綴,而且它的setter會把is替換成set。
// java Person person = new Person("fjh", false); System.out.println(person.getName()); System.out.println(person.isMarried());
// kotlin val person = Person("fjh", false) println(person.name) println(person.isMarried)
自定義訪問器:
class Rectangle(val height: Int, val width: Int) { val isSquare: Boolean get() { return height == width } }
class Rectangle(val height: Int, val width: Int) { fun isSquare(): Boolean = height == width }
Kotlin 須要顯式標註可覆蓋的成員和覆蓋後的成員, 除了用abstract標記的抽象類和抽象成員.
在Kotlin中全部類都有一個共同的超類Any, 這對於沒有超類型聲明的類是默認超類; Any 不是 java.lang.Object, 它除了equals(),hashCode()和toString() 外沒
有任何成員.
若是該類有一個主構造函數,其基類型能夠用主構造函數參數就
地初始化.
open class Base { open fun v() {} fun nv() {} } class Derived() : Base() { final override fun v() {} // 經過final禁止再次繼承 }
若是類沒有主構造函數, 那麼每一個次構造函數必須使用super關鍵字初始化其基類型, 或委託給另外一個構造函數作到這一點.
class MyView : View { constructor(ctx: Context) : super(ctx) constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) }
Kotlin 的接口與 Java 8 相似,既包含抽象方法的聲明,也包含實現。與抽象類不一樣的是,接口沒法保存狀態。它能夠有屬性但必須聲明爲抽象或提供訪問器實現。
interface MyInterface { fun bar() fun foo() { // 可選的方法體 } }
帶有屬性的接口(若是接口定義了getter那麼它的的getter不能引用屬性):
interface MyInterface { val prop: Int // 抽象的 val propertyWithImplementation: String get() = "foo" fun foo() { print(prop) } } class Child : MyInterface { override val prop: Int = 29 }
像在Java中同樣, 類能夠嵌套在其餘類中. 但在Kotlin中, 嵌套類默認和Java中的靜態的內部類相似.
class Outer { private val bar: Int = 1 class Nested { fun foo() = 2 } }
類A在另外一個類B中的聲明 | Java | Kotlin |
---|---|---|
嵌套類 | static class A | class A |
內部類 | class A | inner class A |
密封類用來表示受限的類繼承結構:當一個值爲有限集中的類型、而不能有任何其餘類型時。在某種意義上,他們是枚舉類的擴展:枚舉類型的值集合也是受限的,但每一個枚舉常量只存在一個實例,而密封類的一個子類能夠有可包含狀態的多個實例。
sealed class Expr data class Const(val number: Double) : Expr() data class Sum(val e1: Expr, val e2: Expr) : Expr() object NotANumber : Expr()
咱們常常建立一些只保存數據的類。在這些類中,一些標準函數每每是從數據機械推導而來的。在 Kotlin 中,這叫作 數據類 並標記爲 data :
data class User(val name: String, val age: Int)
編譯器自動從主構造函數中聲明的全部屬性導出如下成員:
在不少狀況下, 咱們須要複製一個對象改變它的一些屬性, 但其他部分保持不變. copy()函數就是爲此而生成.
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
val fjh = User(name = "fjh", age = 22) val olderFjh = fjh.copy(age = 23)
一個解構聲明同時建立多個變量:
class Person(val name: String, var age: Int) { operator fun component1() = name operator fun component2() = age } fun main(args: Array<String>) { val (name, age) = Person("fjh", 22) println(name) println(age) }
會被編譯成一下代碼:
val name = person.component1() val age = person.component2()
componentN() 函數須要用 operator 關鍵字標記,以容許在解構聲明中使用它們.
類能夠繼承一個接口,並將其全部共有的方法委託給一個指定的對象:
interface Base { fun print() } class BaseImpl(val x: Int) : Base { override fun print() { print(x) } } class Derived(b: Base) : Base by b fun main(args: Array<String>) { val b = BaseImpl(10) Derived(b).print() // 輸出 10 }
能夠覆蓋你想要修改的方法.
有一些常見的屬性類型,雖然咱們能夠在每次須要的時候手動實現它們, 可是若是可以把他們只實現一次並放入一個庫會更好。例如包括:
- 延遲屬性(lazy properties): 其值只在首次訪問時計算;
- 可觀察屬性(observable properties):監聽器會收到有關此屬性變動的通知;
- 把多個屬性儲存在一個映射(map)中,而不是每一個存在單獨的字段中。
class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value has been assigned to '${property.name} in $thisRef.'") } } class Example { var p: String by Delegate() }
object關鍵字不一樣於class, 它會聲明一個類並建立一個實例.
使用場景:
Kotlin中的類不能有靜態成員, 而用包級別函數和對象聲明替代.
class MyClass { // 能夠省略伴生對象的名稱 companion object Factory { fun create(): MyClass = MyClass() } } val instance = MyClass.create()
即便伴生對象的成員看起來像其餘語言的靜態成員,在運行時他們仍然是真實對象的實例成員.
val instance = MyClass.Factory.create()
fun countClicks(window: Window) { var clickCount = 0 window.addMouseListener(object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { clickCount++ } }) }
Kotlin 同 C# 和 Gosu相似,可以擴展一個類的新功能而無需繼承該類或使用像裝飾者這樣的任何類型的設計模式。這經過叫作擴展的特殊聲明完成。Kotlin 支持 擴展函數 和 擴展屬性。
fun <T> MutableList<T>.swap(index1: Int, index2: Int) { val tmp = this[index1] // 「this」對應該列表 this[index1] = this[index2] this[index2] = tmp }
擴展不能真正的修改他們所擴展的類; 調用的擴展函數是由函數調用所在的表達式的類型來決定的,而不是由表達式運行時求值結果決定的。
open class C class D: C() fun C.foo() = "c" fun D.foo() = "d" fun printFoo(c: C) { println(c.foo()) } printFoo(D()) // 輸出c
擴展屬性不能有初始化器
val <T> List<T>.lastIndex: Int get() = size - 1
class MyClass { companion object { } // 將被稱爲 "Companion" } fun MyClass.Companion.foo() { // …… }
kotlin中目錄和包不須要對應;沒有import static。
源文件一般以包聲明開頭, 若是沒有指明包, 該文件的內容屬於無名字的默認包:
package utry // ......
有多個包會默認導入到每一個Kotlin文件中:
根據目標平臺還會導入額外的包:
若是出現名字衝突, 可使用 as 關鍵字在本地重命名衝突項來消歧義:
import foo.Bar // Bar 可訪問 import bar.Bar as bBar // bBar 表明「bar.Bar」
import 也能夠用來導入:
在 Kotlin 中有這四個可見性修飾符: private 、protected 、 internal 和 public。若是沒有顯式指定修飾符的話,默承認見性是public 。
Kotlin中沒有Java的包私有, 而提供了internal(模塊內部可見).
可見性修飾符 internal意味着該成員只在相同模塊內可見。更具體地說,一個模塊是編譯在一塊兒的一套 Kotlin 文件:
- 一個 IntelliJ IDEA 模塊;
修飾符 | 類成員 | 頂層聲明 |
---|---|---|
public | 全部地方可見 | 全部地方可見 |
internal | 模塊中可見 | 模塊中可見 |
protected | 子類中可見 | --- |
private | 類中可見 | 文件中可見 |
enum class Color(val r: Int, val g: Int, val b: Int){ RED(255, 0, 0), GREEN(0, 255, 0), BLUE(0, 0, 255) fun rgb() = (r * 256 + g) * 256 + b }
用when處理枚舉類型:
fun getName(color: Color) = when (color) { Color.RED -> "Apple" Color.GREEN -> "Hat" Color.BLUE -> "Sky" }
顯式導入枚舉常量後:
import Color.* fun getName(color: Color) = when (color) { RED -> "Apple" GREEN -> "Hat" BLUE -> "Sky" }
能使用任何表達式做爲分支條件:
fun mix(c1: Color, c2: Color) = when (setOf(c1, c2)) { setOf(RED, GREEN) -> "Apple" setOf(RED, BLUE) -> "Hat" setOf(GREEN, BLUE) -> "Sky" else -> throw Exception("Dirty color") }
若是沒有給when表達式提供參數, 那麼分支條件就是任意的布爾表達式。
interface Expr class Num(val value: Int) : Expr class Sum(val left: Expr, val right: Expr) : Expr fun eval(e: Expr): Int = if (e is Num) { // 這個塊內e被智能轉換成Num 所以不須要下面這行代碼 // val n = e as Num e.value } else if (e is Sum) { // 這個塊內e被只能轉換成Sum eval(e.right) + eval(e.left) } else { throw IllegalArgumentException("Unknown expression") } fun main(args: Array<String>) { println(eval(Sum(Sum(Num(1), Num(2)), Num(4)))) } // 輸出 7
代碼塊中最後的表達式就是結果, 在全部使用代碼塊並指望獲得結果的地方成立(除了常規函數).
fun eval(e: Expr): Int = when (e) { is Num -> e.value is Sum -> eval(e.right) + eval(e.left) else -> throw IllegalArgumentException("Unknown expression") }
while循環語法與java中相同:
// 1到100 for (i in 1..100) { println(i) } // 100到1 步長爲2 for (i in 100 downTo 1 step 2) { println(i) }
val binaryReps = TreeMap<Char, String>() for (c in 'A'..'F') { binaryReps[c] = Integer.toBinaryString(c.toInt()) } for ((letter, binary) in binaryReps) { println("$letter = $binary") }
fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z'
fun recognize(c: Char) = when(c) { in '0'..'9' -> "It's a digit!" in 'a'..'z', in 'A'..'Z' -> "It's a letter!" else -> "I don't know..." }
Kotlin的異常處理基本和Java相似,不一樣的是Kotlin的try和throw能做爲表達式使用:
val percentage = if (number in 0..100) number else throw IllegalArgumentException("$number is not between 0 and 100")
throw表達式的類型爲Nothing。
fun readNumber(reader: BufferedReader) { val number = try { Integer.parseInt(reader.readLine()) } catch (e: NumberFormatException) { null } println(number) }
try表達式的值語句主題的最後一個表達式的值, 若是捕獲到了異常,那catch塊的最後一個表達式就是結果。
Kotlin 的類型系統旨在從咱們的代碼中消除 NullPointerException 。NPE 的惟一可能的緣由
多是:
Kotlin對可空類型顯式支持, 這是一種指出程序中哪些變量和屬性容許爲null的方式.
全部常見類型默認都是非空的, 除非用?標記爲可空.
var a: String = "abc" a = null // 編譯錯誤
var a: String? = "abc" a = null // OK
可空類型不能訪問類型的成員:
var a: String? = "abc" println(a.length) // 編譯錯誤
可是在檢查非空後能夠訪問成員:
var a: String? = "abc" if (a != null) println(a.length) // 以及... println(when { a != null -> a.length else -> return })
安全調用操做符 ?. 是處理可空類型最安全有效的一種工具, 他把一次null檢查和一次方法調用合併成一個操做.
var a: String? = "abc" println(a?.toUpperCase()) println(a?.length)
若是調用的是非空值的方法, 方法會正常執行; 若是值是null, 方法不會執行, 表達式的值爲null; 表達式的類型爲可空類型.
Elvis運算符 ?: 第一個運算參數不爲null, 結果就是第一個參數, 不然結果是第二個參數.
var a: String? = null println(a ?: "abc") println(a ?: throw IllegalArgumentException()) println(a ?: return)
你能夠用 !! 來告訴編譯器這個值不會爲null, 並準備好了接收NPE異常.
var a: String? = null var b: String = a!! //會在這裏拋出NPE println(b.length)
as? 運算符嘗試把值轉換成指定類型, 若是值不是合適的類型就返回null.
class Person(val firstName: String, val lastName: String) { override fun equals(o: Any?): Boolean { val otherPerson = o as? Person ?: return false return otherPerson.firstName == firstName && otherPerson.lastName == lastName } override fun hashCode(): Int = firstName.hashCode() * 37 + lastName.hashCode() }
fun verifyUserInput(input: String?) { if (input.isNullOrBlank()) { println("Please fill in the required fields") } } fun main(args: Array<String>) { verifyUserInput(" ") verifyUserInput(null) }
fun String?.isNullOrBlank(): Boolean = this == null || this.isBlank()
在 Kotlin 中, 全部東西都是對象, 但一些類型能夠有特殊的內部表示——例如數字, 字符和布爾值能夠在運行時表示爲原生類型值.
Kotlin 處理數字在某種程度上接近 Java, 可是並不徹底相同. 例如對於數字沒有隱式拓寬轉換, 另外有些狀況的字面值略有不
同.在kotlin中字符不是數字.
123L // 十進制Long 0x0F // 十六進制 0b00001011 // 二進制 123.5 // Double 123.5e10 // Double 123.5f // Float
不支持8進制
從1.1起, kotlin的數字字面值中能夠加入下劃線來使數字更易讀:
val oneMillion = 1_000_000
在Java平臺下數字會物理存儲爲JVM的原生類型; 在須要可空引用或泛型時, 會將數字裝箱.
val a: Int = 10000 print(a === a) // true val boxedA: Int? = a val anotherBoxedA: Int? = a print(boxedA == anotherBoxedA) // true print(boxedA === anotherBoxedA) // false
Kotlin的相等性
- 引用相等, 由===檢查;
- 結構相等, 由equals檢查.
a == b
可被翻譯爲a?.equals(b) ?: (b === null)
== 可被重載而 === 不行
每一個數字類型支持以下的轉換:
Kotlin支持數字運算的標準集, 運算被定義爲相應的類成員(但編譯器會將函數調用優化爲相
應的指令).操做符可被重載.
沒有特殊字符來表示位運算,只能中綴方式調用命名函數:
val x = (1 shl 2) and 0x000FF000
字符用Char類表示;字符不能被看成數字, 可是可用toInt()
轉換爲Int; 須要可空引用時也會被裝箱.
布爾用Boolean類表示, 若須要可空引用布爾會被裝箱.
數組使用Array類來表示, 定義了get和set函數(在操做符重載中對應[]), size以及成員函數.
arrayOf(1, 2, 3) // array [1, 2, 3]。 arrayOfNulls(3) // array [null, null, null] Array(5, { i -> (i * i).toString() }) // ["0", "1", "4", "9", "16"]
字符串使用String 表示; 字符串中的字符可用索引訪問: s[i]
; 可用for遍歷字符串:
for (c in str) { println(c) }
原生字符串 使用"""
分界符括起來,內部沒有轉義而且能夠包含換行和任何其餘字符:
val text = """ for (c in "foo") print(c) """ println(text) val text2 = """ |for (c in "foo") |print(c) """.trimMargin() // 用`.trimMargin()`去除前導空格 println(text2) val text3 = """ >for (c in "foo") >print(c) """.trimMargin(">") // 用`.trimMargin()`去除前導空格 println(text3) /* output: for (c in "foo") print(c) for (c in "foo") print(c) for (c in "foo") print(c) */
相似Object, Any是全部非空類型的超類型. 它除了equals(),hashCode()和toString() 外沒有任何成員. 若是須要調用Object的方法, 能夠把值轉換成java.lang.Object來調用.
與Java中的void功能同樣, 但Unit是一個完備的類型, 能夠做爲類型參數.
interface Processor<T> { fun process(): T } class NoResultProcessor : Processor<Unit> { override fun process() { // ... // 不須要return } }
Nothing類型沒有值, 它用於標記永遠不可能到達的地方. 能夠用Nothing來標記一個永遠不可能返回的函數.
fun fail(message: String): Nothing { throw IllegalStateException(message) }
Nothing? 有一個可能的值 null. 果用 null 來初始化一個要推斷類型的值, 而又沒有其餘信息可用於肯定
更具體的類型時, 編譯器會推斷出 Nothing? 類型.
val x = null // 「x」具備類型 `Nothing?` val l = listOf(null) // 「l」具備類型 `List<Nothing?>
Kotlin中並無本身的集合類, 它的集合類和Java中徹底相同; Kotlin把訪問集合數據的接口和修改集合數據的接口分開了.
Kotlin 的 List
val numbers: MutableList<Int> = mutableListOf(1, 2, 3) val readOnlyView: List<Int> = numbers println(numbers) // 輸出 "[1, 2, 3]" numbers.add(4) println(readOnlyView) // 輸出 "[1, 2, 3, 4]" readOnlyView.clear() // -> 不能編譯 val strings = hashSetOf("a", "b", "c", "c") assert(strings.size == 3)
Kotlin泛型定義與Java相似. Kotlin中沒有通配符,它有兩個其餘的東西:聲明處型變(declaration-site variance)和類型投影(type projections).
List<String> strs = new ArrayList<String>(); List<Object> objs = strs; // Java中禁止這樣
協變: out操做符標註類型參數只用作在方法中返回, 而不會在方法的參數中出現:
abstract class Source<out T> { //Source 被聲明爲在T上協變 abstract fun nextT(): T } fun demo(strs: Source<String>) { val objects: Source<Any> = strs // …… }
逆變: in操做符標註類型參數只能用在方法參數中, 而不能出如今返回值中:
abstract class Comparable<in T> { abstract fun compareTo(other: T): Int } fun demo(x: Comparable<Number>) { val y: Comparable<Double> = x // OK! }
消費者 in, 生產者 out!
使用處的型變.
例如Array
fun copy(from: Array<out Any>, to: Array<Any>) { // …… } fun fill(dest: Array<in String>, value: String) { // …… }
當你不知道泛型的信息時, 可使用星投影:
fun printFirst(list: List<*>) { if (list.isNotEmpty()) { println(list.first()) } }
聲明註解,要將 annotation 修飾符放在類的前面
annotation class Fancy
註解的附加屬性能夠經過用元註解標註註解類來指定:
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION) @Retention(AnnotationRetention.SOURCE) @MustBeDocumented annotation class Fancy
註解能夠有接受參數的構造函數:
annotation class Special(val why: String) @Special("example") class Foo {}
容許的參數:
註解參數不能有可空類型,由於 JVM 不支持將 null 做爲註解屬性的值存儲。
若是註解用做另外一個註解的參數,則其名稱不以 @ 字符爲前綴:
annotation class ReplaceWith(val expression: String) annotation class Deprecated( val message: String, val replaceWith: ReplaceWith = ReplaceWith("")) @Deprecated("This function is deprecated, use === instead", ReplaceWith("this === othe r"))
若是須要將一個類指定爲註解的參數,請使用 Kotlin 類 (KClass)。Kotlin 編譯器會自動將
其轉換爲 Java 類,以便 Java 代碼可以正常看到該註解和參數:
import kotlin.reflect.KClass annotation class Ann(val arg1: KClass<*>, val arg2: KClass<out Any?>) @Ann(String::class, Int::class) class MyClass
Kotlin可使用兩種反射API, Java的反射和Kotlin的反射.
Kotlin的反射API在kotlin.reflect下, Kotlin反射能提供Java中沒有的信息(屬性和可空類型); Kotlin反射API沒有僅限於Kotlin類.
使用Kotlin的反射API須要添加kotlin-reflect的jar
KClass表明了一個類, 對應 java.lang.Class .
可使用MyClass::class的寫法來得到KClass實例; 用MyClass::class.java來得到Java中的class對象; 在運行時, 可使用javaClass來得到Java類, 再訪問.kotlin擴展屬性:
import kotlin.reflect.memberProperties class Person(val name: String, val age: Int) fun main(args: Array<String>) { val person = Person("Alice", 29) val kClass = person.javaClass.kotlin // 或者person::class println(kClass.simpleName) kClass.memberProperties.forEach { println(it.name) } }
使用 :: 來得到一個命名函數的引用:
fun isOdd(x: Int) = x % 2 != 0 val numbers = listOf(1, 2, 3) println(numbers.filter(::isOdd)) // ::isOdd 是函數類型(Int) -> Boolean的一個值 // 輸出 [1, 3]
當上下文中已知函數指望的類型時, :: 能夠用於重載函數。
fun isOdd(x: Int) = x % 2 != 0 fun isOdd(s: String) = s == "brillig" || s == "slithy" || s == "tove" val numbers = listOf(1, 2, 3) println(numbers.filter(::isOdd)) // 引用到 isOdd(x: Int)
或者,你能夠經過將方法引用存儲在具備顯式指定類型的變量中來提供必要的上下文:
val predicate: (Int) -> Boolean = ::isOdd
引用類的成員函數或者成員屬性,或者extension函數,須要加上類名,如String::toCharArray
.
val x = 1 fun main(args: Array<String>) { // println(::x.get()) // 輸出 "1" println(::x.name) // 輸出 "x" }
::x 類型爲KProperty
屬性引用能夠用在不須要參數的函數處:
val strs = listOf("a", "bc", "def") println(strs.map(String::length)) // 輸出 [1, 2, 3]
訪問屬於類的成員的屬性:
class A(val p: Int) fun main(args: Array<String>) { val prop = A::p println(prop.get(A(1))) // 輸出 "1" }
構造函數能夠像方法和屬性那樣引用。他們能夠用於期待這樣的函數類型對象的任何地方:
它與該構造函數接受相同參數而且返回相應類型的對象。
class Foo fun function(factory : () -> Foo) { val x : Foo = factory() } function(::Foo)
args.forEach({ element -> println(element) }) args.forEach{ println(it) } args.forEach(::println)
Kotlin 有三種結構化跳轉表達式, 這些表達式的類型是Nothing:
在 Kotlin 中任何表達式均可以用標籤(表示符後加@, 好比abc@
)來標記。加上標籤後, 就能夠用標籤來限制break和continue.
loop@ for (i in 1..100) { for (j in 1..100) { if (……) break@loop } }
break 跳轉到恰好位於該標籤指定的循環後面的執行點。 continue 繼續標籤指定的循環的下一次迭代。
若是咱們須要從Lambda中返回, 必須加標籤來限制return:
args.forEach forEachBlock@{ if(it == "q") return@forEachBlock println(it) }
能夠去start.spring.io生成一個示例項目
group 'utry' version '1.0-SNAPSHOT' buildscript { ext.kotlin_version = '1.1.4-2' ext.springboot_version = '1.5.2.RELEASE' repositories { // 倉庫的阿里雲鏡像 maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } //jcenter() //mavenCentral() } dependencies { // Kotlin Gradle插件 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // Kotlin整合SpringBoot的默認無參構造函數,默認把全部的類設置open類插件 classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlin_version") classpath("org.jetbrains.kotlin:kotlin-noarg:$kotlin_version") // SpringBoot Gradle插件 classpath("org.springframework.boot:spring-boot-gradle-plugin:$springboot_version") } } apply plugin: 'kotlin' apply plugin: 'war' //Kotlin-spring 編譯器插件,它根據 Spring 的要求自動配置全開放插件。 apply plugin: 'kotlin-spring' apply plugin: 'org.springframework.boot' repositories { // 倉庫的阿里雲鏡像 maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } //jcenter() //mavenCentral() } dependencies { // https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.7.0' // https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.7.0' compile group: 'org.springframework.boot', name: 'spring-boot-starter-web' compile group: 'org.mybatis.spring.boot', name: 'mybatis-spring-boot-starter', version: '1.3.1' compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" testCompile group: 'junit', name: 'junit', version: '4.11' compile('mysql:mysql-connector-java:5.1.13') } compileKotlin { kotlinOptions.jvmTarget = "1.8" } compileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
@SpringBootApplication @EnableSwagger2 class PostApplication { @Bean fun createRestApi(): Docket { return Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("cn.utry")) .paths(PathSelectors.any()) .build() } private fun apiInfo(): ApiInfo { return ApiInfoBuilder() .title("簡單的Demo") .build() } } fun main(args: Array<String>) { SpringApplication.run(PostApplication::class.java, *args) }
@RestController @RequestMapping("/post") class PostController { @Autowired lateinit var postService: PostService @RequestMapping("/", method = arrayOf(RequestMethod.POST)) fun submit(content: String) = postService.submit(content) @RequestMapping("/", method = arrayOf(RequestMethod.GET)) fun query() = postService.query() }
// KotlinTest示例 s should startWith("kot")
Exposed, sql生成框架.
//聲明一張表 object Country : Table() { val id = integer("id").autoIncrement().primaryKey() //Column類型 val name = varchar("name", 50) } SchemaUtils.create(Country)