Chapter one, background

https://www.kotlincn.net/
Copy the code

Chapter two, environment construction

In AS, Java projects add support for Kotlin

New-activity-empty Activity – Select Kotlin and then add kotlin’s environment. AS does two things for us:

1. Then add kotlin’s plugin to your build.gradle project

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
Copy the code

2. Then add the plugin to build. Gradle in your app

id 'kotlin-android'
Copy the code

Gradle directory

C:\Users\93768\. Gradle \wrapper\dists

Chapter 3, built-in types

3.1 basic types

define

六四屠杀

六四屠杀

The difference between

Java has basic types and wrapper types, Kotlin only has wrapper types.

2. In Java, it represents a long integer followed by l or L. KotlIn can only have L (uppercase).

3. Assigning an integer to a Long is ok in Java, but kotlin generates a compilation error.

val e:Int = 10; val f:Long = e; Val g:Long = e.t Long() val g:Long = e.t Long(Copy the code

Unlike Java, Kotlin has unsigned types

5. Different string input forms

Val STR = "CDX" log. e("test", "hello $STR ")Copy the code

6. Introduce === and ==, where === compares reference values and == compares values.

Var str1 = "Hello" val str2 = String("Hello".tochararray ()) // Compares the reference value log.e (" CDX ",(str1 === str2).toString()) // false / / compare the value of the e (" CDX, "(str1 = = str2). The toString ()) / /Copy the code

7. Output as written

TrimIndent () log.e (" CDX ", STR)Copy the code

3.2, arrays,

Array type

六四屠杀

六四屠杀

Note:

Int has integer and integer boxing types, and string has string boxing only.

Example 1: 4 ways to create an Int array

Var arr1 = IntArray(5) {it} var arr2 = IntArray(5) {it} var arr3 = intArrayOf(1) Var arr4 = Array<Int>(5) {it}Copy the code

Example 2: Create a String array

        val arr = arrayOf("Hello", "world")
        Log.e(tag, arr.joinToString())
Copy the code

3.3, interval

Use of closed intervals

Var arr1: IntRange = 1.. 10 Log.e("cdx", arr1.joinToString()) // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 var arr2: CharRange = 'a'.. 'z' Log.e("cdx", arr2.joinToString()) var arr3: LongRange = 1L.. 100L Log.e("cdx", arr3.joinToString())Copy the code

The use of open intervals

Var arr4 = 1 until 10 //[1,10] log. e(" CDX ", arr4.joinToString()) //1, 2, 3, 4, 6, 7, 8, 9Copy the code

4. Progression in reverse order

Var arr5: IntProgression = 10 downTo 1 Log.e("cdx", arr5.joinToString()) //10, 9, 8, 7, 6, 5, 4, 3, 2, 1 var arr6 = 'z' downTo 'a' Log.e("cdx", arr6.joinToString())Copy the code

Interval step size

Var arr7 = 1.. 10 step 2 Log.e("cdx", arr7.joinToString()) // 1, 3, 5, 7, 9Copy the code

1.. 10 and 1.. 10 What are the types of Step 2?

六四屠杀

六四屠杀

3.4. Collection framework

There are several types of collection frameworks

From the variability is divided into: variable set + immutable set

In terms of the nature of the Set, it can be divided into List + Map + Set

The difference between:

Java’s data structures are mutable, but Kotlin’s distinguish between immutable and mutable.

Method 2 for creating immutable lists

Constructor + method creation method

Var List = List<String>(5) {""} var List [0] = "1" var list2 = listOf<String>("Hello", "world") //list2[0] = "1"Copy the code

Three ways to create a mutable List

Var list2 = mutableListOf<Int>(1) var list2 = mutableListOf<Int>(1) var list2 = mutableListOf<Int>(1) var list2 = mutableListOf<Int List1 [8] = 8 List1.set (2, ArrayList<Int>() List1 [3] = 4 log.e (tag, List1.joinTOString ("*")) 5) Log.e(tag, list1.joinToString("*"))Copy the code

Use ArrayList

// The default is :MutableList val list3 = ArrayList<String>() list3.add("a") list3.add("b") list3 += "c Log.e(" CDX ", list3.joinToString()) //cCopy the code

Two ways to create an immutable Map

To + Pair mode

// immutable Map val Map: Map<String, Any> = mapOf("name" to "xiaohong", "age" to 20) val Map = mapOf<String, String>(Pair("name", "zhang SAN "), Pair("age", "10"))Copy the code

Variable Map

// alter Map val map2: MutableMap<String, Any> = mutableMapOf("name" to "xiaohong", "age" to 20) map2["name"] = 3 map2.put("weight", Set for (en in map2.entries) {log. e(" CDX ", "${en.key}->${en.value}")}Copy the code

Pair (of)

val pair = "Hello" to "kotlin" val pair2 = Pair("Hello", Val (x, y) = pair log. e(" CDX ", "first:$first,second:$second,x:$x,y:$y" ) // first:Hello,second:kotlin,x:Hello,y:kotlinCopy the code

We’re going to Triple the number.

Similar to Pair

3.5, functions,

define

Similar to methods in Java.

What is the return type of a function that has no return value?

Unit is similar to the Java void and can be omitted.

    private fun test4(): Unit {

    }
Copy the code

Function VS method

If there is a test class outside the test method, then test is a method.

class Test {
    fun test(): String {
        return ""
    }
}
Copy the code

Function reference

Function references are similar to Pointers in C and can be used for function passing.

Use ** : : ** to get a reference to a function.

What are the references and types of references to method functions

First define the method

    private fun test(str: String): Unit {

    }
Copy the code

Then get a reference to the method

// define fun1 to accept a reference to a method, (String) -> Unit denotes the type of the function. Val fun1: (String) -> Unit = ::testCopy the code

A reference to a method in a class

package com.example.kotlindemo import android.os.Bundle import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.oncreate (savedInstanceState) setContentView(r.layout.activity_main) // Accepts a reference to a method, which is equivalent to what is in parentheses Val fun2: Test.() -> String = Test:: Test val fun3: (Test) -> String = Test:: Test () -> String = test::test; // Call test1(::test) test1(fun1)} / private fun test1(p: (String) -> Unit) {p("Hello")} private fun test(STR: String): Fun Test (): String {return ""}}Copy the code

Object method reference

Val fun1: () -> Unit = test::testCopy the code

Variable-length argument

Vararg, used to modify parameters, becomes variable-length parameters, similar to arrays.

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState) setContentView(r.layout.activity_main) log. e(" CDX ",test("1", "2"))} Vararg fun test(vararg params: String): String {return params.sie.toString (); }}Copy the code

Two ways to accept multiple return values (normal mode, destruct assignment)

class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.oncreate (savedInstanceState) setContentView(r.layout.activity_main2) val test = test() Val (a,b,c) = test() log.e (" CDX ", test.tostring ())} fun test(): val (a,b,c) = test() log.e (" CDX ", test.tostring ())} fun test(): Triple<Int, Long, Double> {return Triple(1, 2L, 3.0)}}Copy the code

The default parameters

class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState) setContentView(r.layout.activity_main2) test(1)} Can also be fun in front test (x: Int, y: Int = 0, z: String = "") {the e (" CDX", "x: $x y: $y z: $z")}}Copy the code

You are advised to place the default parameters

The default parameter is recommended to be placed last or first

Named parameters

class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.oncreate (savedInstanceState) setContentView(r.layout.activity_main2) // Named arguments: Put key/value pairs into this method when passed Fun test(x: Int =1, y: Int, z: x: Int =1, y: Int, z: x: Int =1, y: Int, z: String = "") {log.e (" CDX ", "x :$x y:$y z:$z")}}Copy the code

Chapter four: Preliminary types

4.1. Classes and Interfaces

The definition of a class

1. The default is public

2, if there is no content in the class, {} can be omitted

3. Attributes defined in a class must be initialized.

Define the constructor from the class, using the constructor keyword.

The constructor is a primary constructor and a secondary constructor, requiring that all other constructors must call it.

Several forms of constructors

Primary constructor only, secondary constructor only, primary constructor + secondary constructor, primary constructor omits constructor, primary constructor simplifies

class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.oncreate (savedInstanceState) setContentView(r.layout.activity_main2) val test5 = test5 (1)}} // Only sub constructor class Constructor (x: Int) {var x: constructor(x: Int) {var x: constructor(x: Int) {var x: constructor(x: Int) {var x: constructor(x: Int)}} Constructor (x: Int, y: Int) {this.x = x this.y = y}} Class Test4(x: Int) {var x: Int = x} class Test4(x: Int) {var x: Int = x} Class Test5(var x: Int) {} var x: Int {}Copy the code

Class initialization

The new keyword is not required

The interface definition

interface SimpleInter {
    fun test()
}
Copy the code

Interface implementation

Class Test: SimpleInter {override fun Test () {}} interface SimpleInter {fun Test ()}Copy the code

Add attributes to the interface and implement them

class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) val test = Test(0) test.param = 4 Log.e(" CDX ", test.param.tostring ())}} interface TestInterface {var param: Int fun test()} class test(var x: Int) : TestInterface {override var param: Get () {return x} set(value) {this.x = value} Override fun test() {}}Copy the code

Definition of an abstract class

Abstract class AbsTest {// means abstract method abstract fun test1() // the open method must be added to tell the compiler, Open fun test2() {}Copy the code

The implementation of the idle class

// Interface inheritance: must add () this is not the same as interface implementation, interface does not need to add () class Test: AbsTest() { override fun test1() { } override fun test2() { super.test2() } }Copy the code

Inheriting a common class requirement

Inherit A normal class A, which must be open decorated.

Methods of a class cannot be overridden

A method of a class that cannot be overwritten increases final.

// To inherit a class, the class must be open class Test2: Test() {// override fun test2() {// super.test2() // override fun test2() {// override fun test2() //}} // interface inherit: This is not the same as the implementation of the interface, which does not need to add () open class Test: AbsTest() {override fun test1() {} Final override fun test2() {super.test2()}} abstract class AbsTest {// indicates an abstract method Open fun test2() {} // The default is not fun test3() {}}.Copy the code

Field use

define

In a get or set method, this property is represented.

Field use

class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) val person = Person(25, Log.e(" CDX ", person.tostring ())}} class person (age: Int, name: String) {var age: Int = age get() {// field = age return field} set(value) {field = value} var name: String = name override fun toString(): String { return "$age,$name" } }Copy the code

4.2. Extended methods

define

Add custom methods to a class without changing the source code of the class.

How to implement

class MainActivity2 : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)

        Log.e("cdx", "abc".times(4))
    }

    fun String.times(times: Int): String {
        var builder = StringBuilder()
        for (i in 0 until times) {
            // 这里的this只得调用者本身
            builder.append(this)
        }
        return builder.toString()
    }
    
}
Copy the code

4.3. Empty type safety

The null type accesses the property

var str: String? = null // use? Val length = STR? .length; //null Log.e("cdx", length.toString())//nullCopy the code

Cast to a non-null type

Pass two!! Changes a nullable type to a non-nullable type

Var STR: String? = "Hello" // pass two! Str1 = STR!! ; Log.e("cdx", str1.length.toString())Copy the code

Elvis operator.

Var STR: String? = null // elvis operator, if STR? Val length = STR? .length ? : 0 Log.e("cdx", length.toString()) //0Copy the code

The inheritance relationship of null types

Small range (String) can be given to large range (String?) Assignment, but large cannot be assigned to small.

Var x: String = "a" var y: String? = "b" // large range assigned to small range, compiler error //x = y // small range assigned to large range, no problem y = xCopy the code

Platform type

* * * * definition

1. Types declared in Java are called platform types in Kotlin.

2. This type of null checking will be relaxed.

example

Let’s start by defining a Person class, which is a Java class.

package com.example.kotlindemo; public class Person { public String name; public String getTitle(){ return null; }}Copy the code

The title type is String!

Var person = person (); Val title = person.title // The compiler doesn't know if title is nullable, so it does a non-nullable check var length = title? .lengthCopy the code

4.4 intelligent type conversion

Kotlin’s type conversion

Kotlin can invoke the attributes of a subclass without casting it to a subclass. (This is not quite the same as Java)

package com.example.kotlindemo import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.oncreate (savedInstanceState) setContentView(r.layout.activity_main2) // The parent class reference points to the subclass object var person = Student(); Log.e(" CDX ", "XXX" + person.name) if (person is Student) {log.e (" CDX ", "XXX" + person.name) if (person is Student) { (person as Student).name) Log.e("cdx", person.name) } } } interface Person { fun say() } class Student : Person { val name: String = "xh" override fun say() { } }Copy the code

scope

class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState) setContentView(r.layout.activity_main2) // scope var value: String? // log.e (" CDX ", value.length.toString()); if (value ! = null) {// In parentheses, the compiler intelligently changes the type of value to String, which is not null. Log.e("cdx", value.length.toString()); } log. e(" CDX ", value? .length.toString()); }}Copy the code

Case where intelligent conversion is not supported

class MainActivity2 : AppCompatActivity() { var tag: String? = null override fun onCreate(savedInstanceState: Bundle?) {super.oncreate (savedInstanceState) setContentView(r.layout.activity_main2) // This place theoretically has non-null judgments, why not the concept of scope? If (tag!) {// If (tag!) {// If (tag!) {// If (tag! = null) { // Log.e("cdx",tag.length.toString()) Log.e("cdx", tag? .length.toString()) } } }Copy the code

A safe conversion of types

* * the as? 六四屠杀

Safe conversion:

If person is of type Student, then convert

If it is not Student, null is returned

Var person = Student(); Return null log. e(" CDX ", (person as? Student)? .name.toString())Copy the code

Advice:

1. Use val as much as possible to declare immutable references to make the meaning of the program clearer.

Chapter 5 expressions

5.1. Read-only Variables and Variables and constants

Variable expression

Var for variables

A read-only variable

Val represents a read-only variable

Read-only variables VS constants

Constant means: never change.

But look at the following example, b in Test, which varies with the value of Math. The value of b varies, so it’s called a read-only variable.

class Test {
    val b: Int
        get() {
            return (Math.random() * 1000).toInt()
        }
}
Copy the code

Constants are required and expressed

1. Only primitive types can be qualified

Can only be defined in the global scope

Must be initialized with a literal immediately

val b = 3
Copy the code

5.2. Branch expressions

If-else expressions (unlike Java, ternary operators)

Note that if-else expressions return values.

        var a: Int = 4
        var c = if (a == 3) 4 else 5
        Log.e("cdx", "c:$c")
Copy the code

When expression

六四屠杀

六四屠杀

When expression – Conditional transfer to branching, shorthand

A way of writing a conditional transfer to a branch

        val a: Any = 4
        val c: Any
        when {
            a is String -> c = a.length
            a == 3 -> c = 3
            else -> c = 5
        }
Copy the code

Simplify the writing

        val a: Any = 4
        val c = when {
            a is String -> a.length
            a == 3 -> 3
            else -> 5
        }
Copy the code

Try-catch expression

Unlike Java, try-catch expressions can have a return value.

        var a = 1
        var b = 0
        val c = try {
            a / b
        } catch (e: Exception) {
            0
        }
Copy the code

5.3 operators and infix expressions

Operator site

https://kotlinlang.org/docs/operator-overloading.html
Copy the code

== operator VS equal

// The following two methods are completely equivalent: val str1 = "Hello" val str2 = "World" var result2 = str1.equals(str2)Copy the code

+ operator VS plus

Var result2 = str1.plus(str2) log. e(" CDX ", result1.toString()) Log.e("cdx", result2.toString())Copy the code

In operator VS contains

        var list = listOf(1, 2, 3, 4)
        var result = 2 in list
        Log.e("cdx", result.toString())
        Log.e("cdx", list.contains(2).toString())
Copy the code

[] operator VS get

Val map = mapOf("name" to "三", "age" to 20) // [] map.get("name").toString()) Log.e("cdx", map["name"].toString())Copy the code

> VS compareTo

        var result1 = 2 > 3
        var result2 = 2.compareTo(3) > 0
        Log.e("cdx", result1.toString())
        Log.e("cdx", result2.toString())
Copy the code

() to invoke

Indicates execution.

Var func = fun() {log.e (" CDX ", "method executed ")} // Invoke func()Copy the code

Custom operators

Step 1: Define an operator that adds two tags to Complex (e.g., humor), such as the + tag, so that the two Complex can recognize each other.

Plus corresponds to the operator +.

package com.example.kotlindemo class Complex(var real: Double, var image: Double) { override fun toString(): String {return "$real + $image"}} String {return "$real + $image"}} Operator fun Complex. Plus (other: Complex): operator fun Complex. Complex {return Complex(this.real + other.real, this.image + other.image)} Operator fun Complex. Minus (other: Complex): Complex { return Complex(this.real - other.real, this.image - other.image) }Copy the code

Step 2: Then call it from inside the page

class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState) setContentView(r.layout.activity_main2) var c1 = Complex(1.0, // result1 = c1 + c2 log. e(" CDX ", result1.toString()) var result2 = c1 - c2 Log.e("cdx", result2.toString()) } }Copy the code

Introduction to the infix expression

Kotlin allows functions to be called without parentheses and periods, so they are called infix functions.

Infix expressions are required and used

1. Only one parameter.

2. Add the infix parameter to indicate that parentheses and periods can be omitted.

class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {super.oncreate (savedInstanceState) setContentView(r.layout.activity_main2) 2.to(3) 2 to 3} Infix fun <A, B> a.too (B: B): Pair<A, B> {return Pair(this, B)}}Copy the code

5.4. Lambda expressions

Passing of anonymous functions

Var func = fun() {log.e (" CDX ", "test")} var func = fun() {log.e (" CDX ", "test")}Copy the code

Calls to anonymous functions

Var func = fun() {log.e (" CDX ", // Invoke () to invoke func()Copy the code

The type of a Lambda expression

Lambda expressions are simplifications of anonymous functions.

Func1 -> Int var func1: () -> Int = {log. e(" CDX ", "test")} Lambda expression with arguments (Int, Int) -> Int var func2: (Int, Int) -> Int = { p1: Int, p2: Int -> Log.e("cdx", "test,$p1 $p2") }Copy the code

Lambda expression returns a value

Is determined by the statement on the last line of the Lambda.

Implement Equals and hashCode for Person

package com.example.kotlindemo import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) val hashSet = HashSet<Person>() Add (Person(" Person ", 15)) log.e (" CDX ", hashSet.size.toString()) } } class Person(var name: String, var age: Int) { override fun equals(other: Any?) : Boolean { Log.e("cdx", "equals") val person = (other as? Person) ? : return false return person.name == name && person.age == age } override fun hashCode(): Int { Log.e("cdx", "hashCode") return name.hashCode() * 7 + age * 5; }}Copy the code

5.6. Implement four operations on String

You need to implement the following effect, which implements string addition, subtraction, multiplication and division.

Analysis:

1. There is no way to modify the String source code, so we need to use extension methods.

2. Resort to custom operators.

package com.example.kotlindemo import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import java.lang.StringBuilder class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) val str: String = "HelloWorld" val result = str - "World" Log.e("cdx", result) val result2 = str * 5 Log.e("cdx", result2) val result3 = str / "l" Log.e("cdx", result3.toString()) } } operator fun String.minus(other: Any): String { return this.replaceFirst(other.toString(), "") } operator fun String.times(time: Int): String { var sb = StringBuilder() for (i in 0 until time) { sb.append(this) } return sb.toString() } operator fun String.div(str: String): Int {// this thing is fun // String a String of little strokes, the length of the stroke is str.lenght, and then the interval is 1, Return this.windowed(str.length, windowed); return this.windowed(str.length); 1) {it == STR} {it == STR}Copy the code

Chapter 6, advanced function

6.1. Higher-order functions

define

The parameter contains a function type or the return value is a function type.

Funtest1 (param: () -> Int) {param() param() param.invoke()} () -> Int {// returns an anonymous function, Return {1}} var arr = intArrayOf(1, 2, 3, 4) arr. ForEach {log. e(TAG, It.tostring ())} log.e (TAG, arr.joinToString()) Val map = arr.map {it * it} log. e(TAG, map.joinToString()))Copy the code

Calls to higher-order functions

Var arr = intArrayOf(1, 2, 3, 4) var arr = intArrayOf(1, 2, 3, 4)Copy the code

Higher-order function calls – Several stages of simplification

Very critical

Var arr = intArrayOf(1, 2, 3, 4) var arr. ForEach ({println("Hello $it")}) Arr.foreach () {println("Hello $it")} // If there are no arguments in the parentheses, then we can leave the parentheses out.Copy the code

Higher order function application – calculation method time

Const ({// (1.. 10000000). The forEach {it} it * / /}) / / optimization into the following styles / / const () {/ / (1.. ForEach {it * it} const {(1.. 10000000).forEach { it * it } }Copy the code

6.2. Inline functions

define

Reduced function calls, optimized performance.

Analysis:

We can see the definition of forEach in the array. kt file, which contains the keyword inline.

public inline fun IntArray.forEach(action: (Int) -> Unit): Unit {
    for (element in this) action(element)
}
Copy the code

We call in code in the following format:

Var arr = intArrayOf(1, 2, 3, 4) var arr. ForEach ({println("Hello $it")})Copy the code

The compiler ends up converting to an inline function.

Var arr = intArrayOf(1, 2, 3, 4) {println(element.toString())}Copy the code

Advantages of inline functions

Reduced function call (mainly reduce the function of the stack, call execution, out of the stack operation), better performance.

Higher-order functions better match inline functions

For example, the following function

class MainActivity2 : AppCompatActivity() {
    val TAG = "cdx"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        const({
            print("1")
        })
    }

    fun const(block: () -> Unit) {
        var start = System.currentTimeMillis()
        block()
        var end = System.currentTimeMillis()
        Log.e(TAG, (end - start).toString())
    }

}
Copy the code

Then let’s look at the compiled code (type Show Kotlin Bytecode)

Let’s take a look at two of the time wasters

Const method called.

Create an anonymous function.

We then optimized the definition of the const method by adding the inline keyword to make it an inline function

            inline fun const(block: () -> Unit) {
            var start = System.currentTimeMillis()
            block()
            var end = System.currentTimeMillis()
            Log.e(TAG, (end - start).toString())
        }
Copy the code

Then let’s look at the compiled code (type Show Kotlin Bytecode)

As we can see, the function calls are eliminated and the performance is higher.

Local return inline function return local return

Imagine a scenario where you don’t print when you encounter a 3. How do you implement this in forEach()? The operation is as follows:

//Kotlin var ints = intArrayOf(1, 2, 3, 4) fun main() { ints.forEach { if (it == 3) return@forEach println(it) } println("Dividing") ints.forEach { if (it == 3)  return println(it) } println("Ending") }Copy the code

Console output:

return@forEach and return print completely different results.

return@forEach will end the loop early, equivalent to a continue;

Return will end the function, in this case the main() function, because Ending is not printed.

A return like return@forEach is called a local return. (The continue function is local-return)

The non-local return of the inline function return

Either locally or globally.

The above return is a non-local return.

Discussion on inline local return and non-local return

Let’s start with the following example, which defines higher-order functions as inline functions:

//Kotlin
inline fun nonLocalReturn(block: ()->Unit){
    block()
}

fun main() {
    println("Starting")
    nonLocalReturn { return }
    println("Ending")
}
Copy the code

The console will print:

Starting

We see a non-local return, a global return.

Then let’s look at the following example, if higher-order functions are defined as non-inline functions:

A non-local return cannot be executed from this location

Why does this happen?

For the first example, because it is an inline function, the inline function does not push or push the code directly into the call, so the return is called inside main, so a non-local retuan global return is generated.

crossinline

noinline

Noline: disables inline functions

Inline attribute

Getters and setters for properties without a back-field can be inline by adding inline to the getters and setters

Class MainActivity2: appactivity () {val TAG = "CDX" var pocket: Double = 0.0 // inline var money: Double inline get() = pocket inline set(value) { pocket = value } override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState) setContentView(r.layout.activity_main2) money = 5.0}}Copy the code

And then let’s compile

Found that the money property is no longer available, the money property has been replaced.

6.3. Several useful higher-order functions

Let, run

Let: When we need to define a variable in a particular scope, let is a good choice.

Var person = person (" person ", 25) val name = person.let {it.name} log.e (TAG, name.tostring ())Copy the code

Run: is similar to let except that one is it and the other is this

Var result = person.run {this.age} log.e (TAG, result.tostring ())Copy the code

Also, the apply

Var person = person (" person ", Var person2 = person.also {it. Name = it. Name + "V2"} log. e(TAG, person2.toString()) var person3 = person.apply { name = "xxx" } Log.e(TAG, person3.toString())Copy the code

6.4 set Transformation and sequence

The filter operation

Filter out the ones that fit and put them in the set

Val result = list.filter {it % 2 == 0} log. e(TAG, result.toString()) // [2, 4]Copy the code

The map operation

Iterate through the array, do the operation, and then put it into the collection

        val list = intArrayOf(1, 2, 3, 4)
        val result = list.map { it * 2 }
        Log.e(TAG, result.joinToString())
Copy the code

FlatMap operation

Flow chart of flatMap operation

1) First pull out the elements

2) Then generate an array from the elements

3) Then concatenate these arrays.

List. Fold (StringBuilder()) {acc, I -> log.e (TAG, int, int, int, int, int); "acc=$acc") Log.e(TAG, i.toString()) acc.append(i) }Copy the code

Lazy sequence where is lazy?

By calling asSequence() and then only by calling forEach methods (fold, Ruduce, sum),

The filter, map, and flatMap methods above are executed

6.5. SAM (Single Abstract Method Transformation) transformation

SAM transformation example

If the anonymous inner class has only one method inside it, then the anonymous inner class can be very simplified, with only one {}.

// SAM example var exe: ExecutorService? = null // anonymous inner class // exe? .submit(object: Runnable {// override fun run() {// log.e (TAG," task executed ") //} //}) Submit ({/ / Log. E (TAG, "task") / /}) / / continue to simplify exe? .submit {log. e(TAG, "task executed ")}Copy the code

Kotlin’s anonymous inner class

// The common way to write an anonymous inner class is object: Runnable {override fun run() {log.e (TAG," task executed ")}}Copy the code