Kotlin和Java一样是静态语言,所有表达式类型在编译期已经确定,public为默认可见性
变量由 var/val+变量名[: 数据类型][?][ = 值] 组成,如
var a = 1
var b: Int
b = 3
var s: String? = null
val language = arrayListOf("java")
language.add("Kotlin")
函数组成为 fun 函数名(参数名: 参数类型, …): 返回值{}
fun max(a: Int, b: Int): Int {
return if (a > b) a else b
}
上面称为代码块函数体,当函数体由单个表达式构成时,可简化为表达式函数体(自动会推导出返回类型)
fun max(a: Int, b: Int) = if (a > b) a else b
如定义一个格式化输出集合的函数
fun joinToString(
collection: Collection,
separator: String,
prefix: String,
postfix: String
): String {
val result = StringBuilder(prefix)
for ((index, element) in collection.withIndex()) {
if (index > 0)
result.append(separator)
result.append(element)
}
result.append(postfix)
return result.toString()
}
val list = listOf("1", "2", "3")
println(joinToString(list, "-", "[", "]"))
在常规调用中,必须按照参数顺序给定参数,通过带默认值的参数可以省略后面的参数传递,默认参数被编码到被调用的函数内部
fun joinToString(
collection: Collection,
separator: String = "",
prefix: String = "",
postfix: String = ""
): String {
val result = StringBuilder(prefix)
for ((index, element) in collection.withIndex()) {
if (index > 0)
result.append(separator)
result.append(element)
}
result.append(postfix)
return result.toString()
}
println(joinToString(list, "-"))
Java需要显式传递所有参数,若需要调用上面的函数,可以用@JvmOverloads注解,会生成
String joinToString(Collection collection, String separator, String prefix, String postfix);
String joinToString(Collection collection, String separator, String prefix);
String joinToString(Collection collection, String separator);
String joinToString(Collection collection);
如果使用命名参数可以省略中间的参数,按照任意顺序给定参数
println(joinToString(list, prefix = "[", postfix = "]"))
由vararg定义,如下为listOf源码
public fun listOf(vararg elements: T): List = if (elements.size > 0) elements.asList() else emptyList()
可通过展开运算符*,把数组元素作为单独的参数来调用
fun main(args: Array) {
val list = listOf("args1", *args)
println(list)
}
中缀调用为特殊的函数调用,如下是一个简单的to()函数定义,会生成一个Pair对象
infix fun Any.to(other: Any) = Pair(this, other)
使用的时候会自动解构声明
val (number, name) = 1 to "one"
println("$number")
println("$name")

map的生成和遍历使用到了中缀调用
val map = mapOf(1 to "one", 7 to "seven")
for ((number, name) in map) {
println("$number:$name")
}
如新建一个test.kt文件,创建max()方法,其不属于任何类
package com.demo.demo1
fun max(a: Int, b: Int): Int {
return if (a > b) a else b
}
会被编译Java的静态函数
public class TestKt {
public static int max(int a, int b) {
if (a > b)
return a;
else
return b;
}
}
如果需要修改顶层函数生成的类的名称,可以在包名前添加注解
@file:JvmName("MyTest")
package com.demo.demo1
fun max(a: Int, b: Int): Int {
return if (a > b) a else b
}
同理,test.kt文件存放属性
package com.demo.demo1
var a = 0
val b = 1
const val c = 2
会被编译Java的静态域
public class TestKt {
public static int a = 0;
public static int b = 1;
public static final int c = 2;
}
把要扩展的类/接口的名称放到即将添加的函数前面,如下扩展String类新增lastChar()方法
fun String.lastChar(): Char = this.get(this.length - 1)
println("Kotlin".lastChar())
在Java中访问扩展函数(放在test.kt)
TestKt.lastChar("Kotlin");
如下定义扩展属性,因为String内容不可变,所以没有setter()
val String.lastChar: Char
get() = this.get(length - 1)
var java.lang.StringBuilder.lastChar: Char
get() = get(length - 1)
set(value: Char) {
setCharAt(length - 1, value)
}
当Java中访问扩展属性(放在test.kt),需要显示调用getter()
TestKt.getLastChar("Java");
如下类,在存储时需要验证各个字段的有效性
class User(val id: Int, val name: String, val address: String)
fun saveUser(user: User) {
if (user.name.isEmpty()) {
throw IllegalArgumentException("can't save user ${user.id} : empty name")
}
if (user.address.isEmpty()) {
throw IllegalArgumentException("can't save user ${user.address} : empty address")
}
}
局部函数可使用可使用外层函数的参数,如下抽取为通用的验证方法
class User(val id: Int, val name: String, val address: String)
fun saveUser(user: User) {
fun validate(value: String, field: String) {
if (value.isEmpty()) {
throw IllegalArgumentException("can't save user ${user.id} : empty $field")
}
}
validate(user.name, "name")
validate(user.address, "address")
}
若User和saveUser为系统的对象,我们不能对其原方法改动,可将其作为扩展函数
class User(val id: Int, val name: String, val address: String)
fun saveUser(user: User) {
//原生方法
}
fun User.validateBeforeSave(value: String, field: String) {
if (value.isEmpty()) {
throw IllegalArgumentException("can't save user ${id} : empty $field")
}
}
fun MySaveUser(user: User) {
user.validateBeforeSave(user.name, "name")
user.validateBeforeSave(user.address, "address")
saveUser(user)
}
可在字符串中通过$引用变量
fun main(args: Array) {
val name = if (args.size > 0) args[0] else "Kotlin"
println("Hello,$name")
}
还可以用${}引用表达式
fun main(args: Array) {
if (args.size > 0) {
println("Hello,${args[1]}")
}
}
fun main(args: Array) {
println("Hello,${if (args.size > 0) args[0] else "Kotlin"} ")
}
如下Java代码返回null,因为split()接收的是一个正则表达式,点会被作为任意字符
String s = "12.34";
System.out.println(Arrays.toString(s.split(".")));
而在Kotlin中,可显式声明正则
val s = "12.34"
println(s.split("\\.".toRegex()))
三重引号可避免转义字符
println("""C:\\Users\\User\\Desktop""")
还可以处理前缀及其前面的空格(默认为|),如下用.当前缀,
println(""".A
.B
. C
""".trimMargin("."))
上面输出
A
B
C