The craftsman may be late for work, but he is never absent, so he decided to share his cloud notes

In particular, the Kotlin series of articles focuses on Java differences and does not list the same parts as Java. With the iteration of the official version of Kotlin, some of the grammar may change, so be sure to pay attention. You can understand the essence of the language, and the difference is only a matter of grammar. It is recommended that you do not pay too much attention to the grammar, but understand the principle behind it.

background

This article in these knowledge points are kotlin relative to Java unique new capability mechanism, so there is no difference with Java contrast, these new capabilities are kotlin source Standard. Kt defined in the function or extension function, The official called range tool function (kotlinlang.org/docs/refere…

let

The let extension function is actually a scope function, and is a good choice when we need to define variables in a particular scope. In addition let function with? Another use of the. Operator is to avoid writing null operations. Here are the use cases:

// Use case 1: define variables in a specific scope
testObj.let {
   it.func() // Where it is the testObj instance.var localValue = 1 // Define variables in a specific scope. }// Use case 2: Avoid writing null operations
var obj: TestObjClass? = null
valret = obj? .let{// if obj is not null, the let body is executed, otherwise null is returned
   it.func() // Func returns a value to ret when obj is not null
}
Copy the code

Kotlin in the let extension function implementation principle source code:

/ / 【 craftsman if water to add WeChat yanbo373131686 contact me, concern WeChat public number: code farmers a daily topic Without permission is strictly prohibited reproduced, https://blog.csdn.net/yanbober]

// Let is an inline extension function that extends any type, represented here as a paradigm
// Take a function type argument (a lambada expression) and return the return value of the function call with the function type argument
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) - >R): R {
	/ / contract
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    // You can see that the function with its arguments is called, passing the arguments as the instance of the object on which the let function was called, and returning the value as the value returned by the function argument call
    return block(this)}Copy the code

with

The with function is actually a shorthand wrapper for calling multiple methods or properties of the same class. In this case, you can simply call the method of the class without having to repeat the class name. Typical application scenarios are as follows:

with(obj) {
    prop // Equivalent to obj. Prop
    fun(a) // equivalent to obj.fun()
}

/ / case
class User(var name: String, var age: Int)

val user = User("gongjiangruoshui".18)
val ret = with(user) {
        println("name is $name, age is $age") // The prefix user. Is not required
        1000 / / the return value
    }
Copy the code

Kotlin with common function implementation source code as follows:

/ / 【 craftsman if water to add WeChat yanbo373131686 contact me, concern WeChat public number: code farmers a daily topic Without permission is strictly prohibited reproduced, https://blog.csdn.net/yanbober]

// Let is an inline function
// Special attention! The block argument is a function type with a receiver. This in T.()->R represents an instance of itself, so it can be omitted; This in ()->R represents an instance of an external class, so it cannot be omitted.
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T. () - >R): R {
    / / contract
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    // The receiver argument calls its own function with a receiver, so you can internally omit this and finally return the return value of the function with a receiver
    return receiver.block()
}
Copy the code

run

Kotlin provides an extension function implementation and a normal function implementation for Run; The implementation of ordinary functions can also be said to address the scenario of defining variables in a particular scope; In fact, the implementation of the extension function can be said to be a combination of the two functions, let and with. The run extension function makes up for the problem that let must use it parameters instead of objects in the function body. It can be omitted like the with function and directly access the public properties and methods of the instance. On the other hand, the run extension makes up for the problem of the null object passed to the with function. Typical application scenarios are as follows:

// Run extension function use case
class MultiportService(var url: String, var port: Int) {
    fun prepareRequest(a): String = "Default request"
    fun query(request: String): String = "Result for query '$request'"
}

fun main(a) {
    val service = MultiportService("https://example.kotlinlang.org".80)

	//service. Replace service? Can also achieve the purpose of omitting empty
    val result = service.run {
        port = 8080 // Access attributes directly
        query(prepareRequest() + " to port $port")}// Use let to achieve the same effect
    val letResult = service.let {
        it.port = 8080 // Let internal access object properties must specify it.
        it.query(it.prepareRequest() + " to port ${it.port}")
    }
    println(result)
    println(letResult)
}

// Run normal function use case
fun main(a) {
    val hexNumberRegex = run {
        // Use local variables defined within run
        val digits = "0-9." "
        val hexDigits = "A-Fa-f"
        val sign = "+ -"
        Regex("[$sign]? [$digits$hexDigits] +")}for (match in hexNumberRegex.findAll("+1234 -FFFF not-a-number")) {
        println(match.value)
    }
}
Copy the code

Kotlin run ordinary functions and extension functions to implement the source code as follows:

/ / 【 craftsman if water to add WeChat yanbo373131686 contact me, concern WeChat public number: code farmers a daily topic Without permission is strictly prohibited reproduced, https://blog.csdn.net/yanbober]

// Run the normal function
@kotlin.internal.InlineOnly
// You can see that the let function does exactly the same thing, except that it is not an extension function and can be used freely
public inline fun <R> run(block: () -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

// Run the extension function
@kotlin.internal.InlineOnly
T.()->R; // Let (); // Let (); This in ()->R represents an instance of an external class, so it cannot be omitted.
public inline fun <T, R> T.run(block: T. () - >R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    // This is equivalent to let
    return block()
}
Copy the code

apply

The apply extension is similar to the run extension, except that they return different values. The run extension returns the value of the last line of code in the form of a closure, whereas the apply extension returns the object itself. Therefore, the Apply extension function is generally used for object instance property initialization scenarios (similar to builder mode), and can also be used for multi-level null detection scenarios. Typical application scenarios are as follows:

// Object instantiation scenario
data class Person(var name: String, var age: Int = 0.var city: String = "") {
    fun test(a) { println "666"}}fun main(a) {
	// Construct the object and assign the property
    val adam = Person("Adam").apply {
        age = 32
        city = "London"        
    }
    println(adam)
}

// Multilevel void detection scenario
class Dog {
    fun testDog(a) = println "dog"
}

class Cat {
	var dog: Dog? = null
    fun testCat(a) = println "cat"
}

val cat: Cat? = nullcat? .apply {// Call testCat when cat is not emptytestCat() }? .dog? .apply{// Call testDog when the dog instance in the cat object is not empty
	testDog()
}
Copy the code

Kotlin apply extension function implementation source code as follows:

/ / 【 craftsman if water to add WeChat yanbo373131686 contact me, concern WeChat public number: code farmers a daily topic Without permission is strictly prohibited reproduced, https://blog.csdn.net/yanbober]

// Apply is an inline extension function
// Special attention! The block argument is a function type with a receiver. This in T.()->R represents an instance of itself, so it can be omitted; This in ()->R represents an instance of an external class, so it cannot be omitted.
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T. () - >Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    // Return the calling object itself
    return this
}
Copy the code

also

The only difference is that the return value of a let is different. A let returns the value of the last line in the body of the function as a closure, whereas a also extension returns the object itself. The ALSO extension function is suitable for any scenario of a let function, and can also be used as an intervention in chained programming (without breaking the chain destructor). Here are the use cases:

fun main(a) {
    val numbers = mutableListOf("one"."two"."three")
    Print the content of the element before inserting it
    numbers
        .also { // Insert the chain
            println("The list elements before adding new one: $it")
        }
        .add("four")}Copy the code

Kotlin also extension function implementation principle source code:

/ / 【 craftsman if water to add WeChat yanbo373131686 contact me, concern WeChat public number: code farmers a daily topic Without permission is strictly prohibited reproduced, https://blog.csdn.net/yanbober]

// Same as let, but returns a different value
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) - >Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    // Return the calling object itself
    return this
}
Copy the code

TakeIf and takeUnless

The takeIf and takeUnless extension functions act as a pair of filter operations. These two extension functions allow us to add a state check of the object in a chained call, deciding whether to return null or call the object itself based on the return value in the code block. . Scope functions to make simple if logical effects. Here are the use cases:

/ / case
val number = Random.nextInt(100)
val evenOrNull = number.takeIf { it % 2= =0 } // Return even if it is even, otherwise null is returned
val oddOrNull = number.takeUnless { it % 2= =0 } // Return null if it is even, otherwise return itself

/ / the second case
val str = "Hello"
valcaps = str.takeIf { it.isNotEmpty() }? .toUpperCase()//val caps = str.takeIf { it.isNotEmpty() }.toUpperCase() //compilation error
println(caps)

/ / case 3
fun displaySubstringPosition(input: String, sub: String) {
    // Equivalent to val index = input.indexof (sub); if (index >=0) { println ... }
    input.indexOf(sub).takeIf { it >= 0}? .let { println("The substring $sub is found in $input.")
        println("Its start position is $it.")
    }
}
displaySubstringPosition("010000011"."11")
displaySubstringPosition("010000011"."12")
Copy the code

Kotlin in the takeIf, takeUnless extension function implementation principle source:

/ / 【 craftsman if water to add WeChat yanbo373131686 contact me, concern WeChat public number: code farmers a daily topic Without permission is strictly prohibited reproduced, https://blog.csdn.net/yanbober]

// The two functions are exactly the same, except that they are mutually exclusive
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) - >Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (predicate(this)) this else null
}

@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) - >Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if(! predicate(this)) this else null
}
Copy the code

repeat

Repeat inline function is actually a utility function, how the name, repeated execution, is essentially a for loop, not much to say, and very simple to use. Here are the use cases:

// Repeat print three times, it is the count index
repeat(3) {
    println("exec $it")}Copy the code

Kotlin in the implementation of repeat function principle source:

/ / 【 craftsman if water to add WeChat yanbo373131686 contact me, concern WeChat public number: code farmers a daily topic Without permission is strictly prohibited reproduced, https://blog.csdn.net/yanbober]

@kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) - >Unit) {
    contract { callsInPlace(action) }
	// For one loop, the argument passed is the current index
    for (index in 0 until times) {
        action(index)
    }
}
Copy the code

Kotlin source Standard. Kt defined in the function or extension function we are all analyzed, you should also know how to choose to use.

Hitching Analysis (Timing.ktSource code Tools method)

Kotlin provides another very useful and practical tool method, that is, Timing. Kt code in the source code execution time measurement function. Look directly at the source code analysis below:

/ / 【 craftsman if water to add WeChat yanbo373131686 contact me, concern WeChat public number: code farmers a daily topic Without permission is strictly prohibited reproduced, https://blog.csdn.net/yanbober]

// put a certain amount of time into the earth and return it
public inline fun measureTimeMillis(block: () -> Unit): Long {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    // This is simple
    val start = System.currentTimeMillis()
    block()
    return System.currentTimeMillis() - start
}

// Measure the NanoTime execution time of the block and return
public inline fun measureNanoTime(block: () -> Unit): Long {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    // This is simple
    val start = System.nanoTime()
    block()
    return System.nanoTime() - start
}
Copy the code

The application scenarios are as follows:

fun main(a) {
	// Measure internal code execution time
    val cost = measureTimeMillis {
        testRun()
    }
    println(cost) / / 2000
}

fun testRun(a) {
    Thread.sleep(2000)}Copy the code

So far, really over!

Craftsman Ruoshui plus wechat Yanbo373131686 contact me, follow the wechat public number: Code farmers daily a question is strictly prohibited to reprint without permissionblog.csdn.net/yanbober】