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 to it. Just understand the essence of the language, and the difference is only at the grammar level. It is recommended not to pay too much attention to the grammar.

Kotlin default parameter function

You cannot use named parameter syntax when calling Java methods in Kotlin because Java bytecode does not always retain method parameter information. Kotlin default parameter function definition and use cases are 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]

// Override a test method
fun test(a) = println("other test")

fun test(a: Int = 0, b: Int = 1, c: String = "666") = println("$a$b$c")

Other test 121666 012666 121ccc */
fun testRun(a) {
    test()  // The overloaded no-parameter test method is called
    test(12)
    test(b = 12)  // Named parameter call mode
    Type mismatch. Required: Int Found: String
    //test("888")
    test(a=12, c="ccc")}Copy the code

For overridden methods, the overridden methods owned by a child class use the same default parameter values as the parent class. When overwriting a method that has default parameter values, the default parameter values must be omitted from the method signature. Here’s a case:

open class AnimBase {
    open fun test(a: Int, b: Int = 1, c: String = "666") = println("$a$b$c")}class AnimDog: AnimBase() {
    override fun test(a: Int, b: Int, c: String) {
        super.test(a, b, c)
    }

    // Override methods are not allowed to specify default values for parameter values, either a or B
    An ancient function is not allowed to specify default values for its parameters
    //override fun test(a: Int = 1, b: Int = 1, c: String) {
    // super.test(a, b, c)
    / /}
}

/** Call result: 121666 */
fun testRun(a) {
    val anim = AnimDog()
    anim.test(a = 12)}Copy the code

Kotlin lambada expression

Lambada expressions in Kotlin are generally similar to Java, but have their own special features. The kotlin lambada expression must meet the following requirements:

  • A lambada expression is always surrounded by a curly brace.
  • Its argument, if any, is located at->Previously, the parameter types could be omitted.
  • The executive body is located->After.

By default, the value of the last expression in a Lambada expression is implicitly returned as the value of that lambada expression. We can qualify the return value from a lambada expression with fully qualified syntax. Here’s a case:

/ / 【 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]

//compute is defined as a lambada expression argument
fun testLambada(i: Int = 1, j: Int = 1, compute: (x: Int.y: Int) - >Unit) {
    compute(i, j)
}

fun callBack(a: Int, b: Int): Unit {
    println("a=$a, b=$b")}/** * call result: 1-1 = 0 2 + 4 =6 a=2, b=6 */
fun testRun(a) {
    testLambada { x, y -> println("$x - $y = ${x - y}") }

    testLambada(2.4) { x, y -> println("$x + $y = ${x + y}") }

    testLambada(2.6, ::callBack)
}
Copy the code

Here’s another example:

fun test1(num: Int, exec: () -> Unit) {
    exec()
}

fun test2(num: Int, exec: (i: Int) - >Unit) {
    exec(num)
}

fun test3(num: Int, exec: (i: Int.j: Int) - >Unit) {
    exec(num, 3)}fun main(a) {
    test1(2) {
        // There is no $it
        println("666")}// The it parameter is passed implicitly when there is only one parameter
    test2(3) {
        println("777 $it")}// Multiple parameters must be specified explicitly
    test3(4) { _, _ ->
        println("888")}}Copy the code

Kotlin variable parameter function

Only one method is allowed to have a variable parameter definition and is usually the last one in the argument list. If the variable argument is not the last argument, then the arguments following it need to be passed as named arguments. If the arguments following it are of function type, you can also pass lambada expressions outside the parentheses without specifying a named argument. Here’s a case:

/ / 【 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]

// Use vararg for variable parameter definitions
fun testArgs(vararg strs: String) {
    println(strs.javaClass) // String array type
    strs.forEach { println(it) }
}

/** Call result: class [ljava.lang.string; 666 777 ------------ class [ljava.lang.string; 11 22 */
fun testRun(a) {
    testArgs("666"."777")
    println("-- -- -- -- -- -- -- -- -- -- -- --")

    val args1 = arrayOf<String>("11"."22")
    / / compile error Type mismatch. Required: String Found: kotlin. Collections. The ArrayList < String > / * = Java. Util. The ArrayList < String > * /
    //testArgs(args1)

    // Use the scatter operator *
    testArgs(*args1)
}
Copy the code

Kotlin Infix Notation

Kotlin’s functions can also be called using the infix symbol, if the following three conditions are met:

  • Is a member function or an extension function.
  • Has a single parameter.
  • Declare using the infix keyword.

Here’s an example:

class InfixT (private var age: Int) {
    infix fun add(num: Int) = this.age + num
}

/** Call result: 24 33 */
fun testRun(a) {
    val test = InfixT(12)
    // The following two calls are equivalent and often appear in the underlying kotlin library
    println(test.add(12))   // Normal call
    println(test add 21)    // Infix call
}
Copy the code

Kotlin inline functions

Inlining improves call efficiency, but increases bytecode volume. Its advantages, disadvantages and mechanisms are equivalent to those of inlining functions in other languages. Here’s a case:

inline fun add(a: Int, b: Int) = a + b
Copy the code

As for the principle of inline functions, it is actually very simple. I suggest you go directly to JavAP-c and look at the bytecode differences to understand the advantages and disadvantages.

Kotlin higher order functions

A function is a higher-order function if another function can be passed as an argument. A lambada expression is often used for this purpose. Common lambada expressions are defined:

/ / 【 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 add variable is a function type whose value is equal to a lambada function
val add: (Int.Int) - >Int = { a: Int, b: Int -> a + b }
/ / short
val add: (Int.Int) - >Int = { a, b -> a + b }

// Automatic type inference writing
val sub = { a: Int, b: Int -> a - b }

// Print variable is also a lambada expression with no arguments
val print = { println("666")}//_ represents an argument, but the argument is not used in the body of the function
val mayNull: (Int.Int) - >Int? = {_, _ ->null }

// The variable of the function type of the lambada expression can be null, and null is assigned here
val functionMayNull: (Int.Int) - >Int)? = null
Copy the code

Define a higher-order function and its usage:

// Higher-order function definitions
fun funcHeight(a: Int, b: Int, calculate: (Int.Int) - >Int): Int {
    return calculate(a, b)
}

/** Call result: 22 2 */
fun testRun(a) {
    val add = { a: Int, b: Int -> a + b }
    println(funcHeight(12.10, add))

    println(funcHeight(12.10) { x, y -> x - y })
}
Copy the code

Kotlin anonymous functions

Kotlin’s anonymous functions are mainly used in lambada expressions. Here’s a case:

fun funcHeight(a: Int, b: Int, calculate: (Int.Int) - >Int): Int {
    return calculate(a, b)
}

Function declaration must have a name
//fun (x: Int, y: Int) = x + y

/** Call result: 7 7 */
fun testRun(a) {
    // Anonymous function
    fun (x: Int, y: Int) = x + y

    // A lambada expression
    var ret = funcHeight(3.4, { x, y -> x + y })
    println(ret)

    // Anonymous functions are used in lambada expressions
    ret = funcHeight(3.4.fun (x, y): Int = x + y)
    println(ret)
}
Copy the code

Kotlin closure

Kotlin allows you to change the value of the outer variable ina lambada expression (Java does not allow this, and the outer variable must be final). This feature is actually a closure feature, 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]

/** Call result: 123412345 */
fun testRun(a) {
    var sum = ""

    val strs = arrayOf("1234"."123"."12345")
    strs.filter { it.length > 3 }.forEach {
        / / closures
        sum += it
    }
    println(sum)
}
Copy the code

Kotlin the literal value of the function with the receiver

Kotlin provides the ability to call a function numeric face value from a specified receiver object. Inside the literals, you can call methods on the receiver object without using any additional modifiers, such as the Apply function mechanism provided by Kotlin. This is very similar to extension functions. Here’s an example:

// sub is a function variable of Int
val sub: Int.(arg: Int) - >Int = { arg -> this - arg }

/** Call result: 70 */
fun testRun(a) {
    // The sub function can be called only on Int variables
    println(100.sub(30))}Copy the code

Anonymous function syntax allows us to specify the receive type of a function’s numeric value, so we can declare a function variable with a receiver and then use it. Here’s a case:

/** Call result: 70 */
fun testRun(a) {
    // The numeric value of the function with the receiver is an anonymous function. Note the comparison with the previous example
    val sub1 = fun Int.(arg: Int): Int = this - arg
    println(100.sub1(30))}Copy the code

Non-literal values of functions with a receiver type can be passed as arguments, provided there is a receiver type argument where the receiver function is needed, and vice versa.

For example, the type String.(Int)->Boolean (represents the type of a function with a receiver, is called with a String, takes an Int argument, returns a Boolean value), and is associated with (String, Int)->Boolean (represents the function itself takes two arguments, A String, an Int, returns Boolean, and the first argument String is equivalent to the caller of the previous function of type receiver.

/**
 调用结果:
 true
 true
 true
 true
 true
 */
fun testRun(a) {
    // Represents a literal with a receiver, and determines whether string is equal to an Int
    val equalNum: String.(Int) - >Boolean = { arg -> this.toIntOrNull() == arg }
    println("123".equalNum(123))
    println(equalNum("123".123))

    fun equalNum1(string: String, int: Int): Boolean = string.toIntOrNull() == int
    println(equalNum1("123".123))
    // equalNum1 does not exist
    //println("123".equalNum1( 12))

    // Define a function (the scenario in the concept explanation section above)
    fun equalNum2(op: (String.Int) - >Boolean, a: String, b: Int, c: Boolean) = println(op(a, b) == c)
    // You can pass literal values representing the receiver directly, equivalent (the scenario in the concept explanation section above)
    equalNum2(equalNum, "123".123.true)
    // Pass the normal function callback
    equalNum2(::equalNum1, "123".123.true)}Copy the code

This function ends with the lambada section.

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】