- 字符串字面值可以包含模板表达式 ,即一些小段代码,会求值并把结果合并到字符串中。 模板表达式以美元符($)开头,由一个简单的名字构成:
val s = "abc"
println("$s.length is ${s.length}") // 输出“abc.length is 3”
- 当某个变量的值可以为 null 的时候,必须在声明处的类型后添加 ? 来标识该引用可为空。
如果 str 的内容不是数字返回 null:
fun parseInt(str: String): Int? {
// ……
}
- 次构造函数
//如果类有一个主构造函数,每个次构造函数需要委托给主构造函数,
//可以直接委托或者通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可
class Person(val name: String) {
var children: MutableList<Person> = mutableListOf<Person>();
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}
- is 运算符检测一个表达式是否某类型的一个实例。 如果一个不可变的局部变量或属性已经判断出为某类型,那么检测后的分支中可以直接当作该类型使用,无需显式转换.
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null
// `obj` 在这一分支自动转换为 `String`
return obj.length
}
- for 循环
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
//output
item at 0 is apple
item at 1 is banana
item at 2 is kiwifruit
- when 表达式
when 既可以被当做表达式使用也可以被当做语句使用。如果它被当做表达式, 符合条件的分支的值就是整个表达式的值,如果当做语句使用, 则忽略个别分支的值。(像 if 一样,每一个分支可以是一个代码块,它的值是块中最后的表达式的值。)
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
fun main() {
println(describe(1))
println(describe("Hello"))
println(describe(1000L))
println(describe(2))
println(describe("other"))
}
//output:
One
Greeting
Long
Not a string
Unknown
- 伴生对象
类内部的对象声明可以用 companion 关键字标记:
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
fun main(){
val instance = MyClass().create()
}
可以省略伴生对象的名称,在这种情况下将使用名称 Companion:
class MyClass {
companion object { }
}
val x = MyClass.Companion
请注意,即使伴生对象的成员看起来像其他语言的静态成员,在运行时他们仍然是真实对象的实例成员,而且,例如还可以实现接口:
interface Factory<T>{
fun create(): T
}
class MyClass{
companion object :Factory<MyClass>{
override fun create(): MyClass = MyClass()
}
}
val f:Factory<MyClass> = MyClass
- let函数
使用let函数处理需要针对一个可null的对象统一做判空处理.
let扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,let函数的是一个不错的选择.
object.let{
it.todo()//在函数体内使用it替代object对象去访问其公有的属性和方法
...
}
//另一种用途 判断object为null的操作
object?.let{//表示object不为null的条件下,才会去执行let函数体
it.todo()
}
//具体的使用例子
fun setEmptyView(layoutResId: Int) {
weakRecyclerView.get()?.let {
val view = LayoutInflater.from(it.context).inflate(layoutResId, it, false)
setEmptyView(view)
}
}
- var 和 val 的唯一区别在于 var 既有 getter 又有 setter,val 只有 getter 没有 setter
var a = 3
// var a: Int = 3
// 省略可推断类型.
var b = 3
// Warning: Redundant setter.
get() = field
// Warning: Redundant setter.
set(value) {
field = value
}
// 编译错误: Property must be initialized or be abstract.
// var c: Int
// 编译错误: Property must be initialized.
// var d
// get() = 3
val e
get() = 3
var f
get() = 3
// Warning: Redundant setter.
set(value) {}
val 属性没有 setter,就像 private val a = 0 的属性与 Java 中的 private final 字段完全相同。
幕后字段 field,用来在 getter 和 setter 中访问当前属性,相当于 Java 中的 private 字段。
一定条件下属性可以不赋予初始化值,对应在 Java 中不会生成字段,只会生成 getter 和 setter
收录于这个人的博客
- 关键字with
它是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式。可以看出with函数是接收了两个参数,分别为T类型的对象receiver和一个lambda函数块.
fun main(args: Array<String>) {
val user = User("带哥", 32, "110911")
val result = with(user) {
println("my name is $name, I am $age years old, my phone number is $phoneNum")
110
}
println("result: $result")
}
//java
public static final void main(@NotNull String[] args) {
User user = new User("带哥", 32, "110911");
String var4 = "my name is " + user.getName() + ", I am " + user.getAge() + " years old, my phone number is " + user.getPhoneNum();
System.out.println(var4);
int result = 110;
String var3 = "result: " + result;
System.out.println(var3);
}
- run函数
它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理.
fun main(args: Array<String>) {
val user = User("带哥", 32, "110911")
val result = user.run {
println("my name is $name, I am $age years old, my phone number is $phoneNum")
110
}
println("result: $result")
}
- apply关键字
是一个扩展函数,把this作为参数传递,它返回this(即它本身).可以从下面的例子看到.
class User(val name: String, val age: Int, val phoneNum: String)
fun main(args: Array<String>) {
val user = User("hub", 11, "123123123")
val result = user.apply {
println("my name is $name, I am $age years old, my phone number is $phoneNum")
}
println("result: $result")
}
//output
//my name is hub, I am 11 years old, my phone number is 123123123
//result: User@48140564
//实际运用中
// 正常方法
fun createInstance(args: Bundle) : MyFragment {
val fragment = MyFragment()
fragment.arguments = args
return fragment
}
// 改进方法
fun createInstance(args: Bundle)
= MyFragment().apply { arguments = args }
- also
T.let返回不同类型的值,而T.also返回T本身即this.
class User(val name: String, val age: Int, val phoneNum: String)
fun main(args: Array<String>) {
val user = User("max", 11, "123123123")
//注意打印加花括号,否则打印的是地址
//使用it还代替this
val result = user.also {
println("my name is ${it.name}, I am ${it.age} years old, my phone number is ${it.phoneNum}")
}
println("result: $result")
}
最后我们看看这些函数直接的区别.图片来自这里.