Kotlin记录知识点(一)

  1. 字符串字面值可以包含模板表达式 ,即一些小段代码,会求值并把结果合并到字符串中。 模板表达式以美元符($)开头,由一个简单的名字构成:
val s = "abc"
println("$s.length is ${s.length}") // 输出“abc.length is 3”
  1. 当某个变量的值可以为 null 的时候,必须在声明处的类型后添加 ? 来标识该引用可为空
    如果 str 的内容不是数字返回 null:
fun parseInt(str: String): Int? {
    // ……
}
  1. 次构造函数
//如果类有一个主构造函数,每个次构造函数需要委托给主构造函数, 
//可以直接委托或者通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可
class Person(val name: String) {
    var children: MutableList<Person> = mutableListOf<Person>();
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}
  1. is 运算符检测一个表达式是否某类型的一个实例。 如果一个不可变的局部变量或属性已经判断出为某类型,那么检测后的分支中可以直接当作该类型使用,无需显式转换.
fun getStringLength(obj: Any): Int? {
    if (obj !is String) return null

    // `obj` 在这一分支自动转换为 `String`
    return obj.length
}
  1. 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
  1. 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
  1. 伴生对象
    类内部的对象声明可以用 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
  1. 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)
        }
    }
  1. varval 的唯一区别在于 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
收录于这个人的博客

  1. 关键字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);
   }
  1. 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")
}
  1. 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 }
  1. 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")
}

最后我们看看这些函数直接的区别.图片来自这里.

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章