官网 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)