The first line of code, Third Edition - Chapter 2 (notes)

Explore new languages and get started with Kotlin programming


1.1 kotlin's position in Android

Since the birth of Android, it has only provided Java as a language to develop applications
At the I/O conference in 2017, Google announced that Kotlin, as the first-class development language of Android, is on an equal footing with Java
At the I/O conference in 2019, Google announced that Kotlin has become the first development language. Of course, Java development is still useful
So far, in the foreign Android Market, the vast majority of apps have been developed using Kotlin.
Some official videos and open source projects of Google use Kotlin, and Kotlin is becoming more and more important.

1.2 historical process of kotlin

In 2011, JetBrains released the first version of Kotlin
2012 Kotlin open source
In 2016, Kotlin released the official version of 1.0, and IDEA also supports the use of Kotlin
In 2017, Google announced that Kotlin became the first-class language of Android
In 2019, Google announced that Kotlin became the first language of Android

1.3 programming language

programing languageeffectlanguage
Programming languageThe compiler compiles the source code we write into binary that can be recognized by the computer at one time and runs it directlyC,C++
Interpretive languageThe interpreter will read the source code line by line, interpret these source codes into binary data in real time, and then execute them. The efficiency will be poorPython,JavaScript

2 variables and functions

2.1 variables

Kotlin is very different from Java variables
Java: integer variable (int a), string variable (String b)
Kotlin defines variables in only two keyword declarations
val(value abbreviation) is used to declare an immutable variable, that is, after the initial assignment, the variable can no longer be modified, corresponding to the Java final variable
var(variable abbreviation) is used to declare a variable, that is, after the initial assignment, the content of the variable can also be changed. Non final variables corresponding to Java

After Kotlin writes a line of code, semicolons are not required; , and Java is required, so you need to pay attention when changing java to Kotlin

var a = 10 //Automatically declared as int type data
var b = "How do you do" //Automatically declare as string type data

In Kotlin, var or val is used to define variables for any type of data, because it will automatically identify what type of data it is. This is Kotlin's type derivation mechanism. However, if our variable is delayed assignment, it cannot be deduced automatically. At this time, we need to explicitly declare the type of the variable

//When a variable is explicitly declared, the Kotlin derivation mechanism will not deduce the variable. When you try to assign a String to a, an exception will be thrown
var a:Int = 10
Java basic data typeKotlin object data typedata type
longLongLong integer
floatFloatSingle precision floating point
doubleDoubleDouble precision floating point
byteByteByte type

In Java, few people will take the initiative to use final, which leads to the fact that they don't know where this variable has been modified in the later stage, which leads to the increase of the insertion cost. In Kotlin, when defining a variable at the beginning, you must define whether it is var or val, and actively declare whether the variable can be changed.
Aunt Guo said that val (immutable variable) should be used first. When you need to change the variable later, change Val to var

2.2 function

Methods and functions

In fact, there is no difference between methods and functions, but the names are different. They are function and method translated from English. Methods are often called in Java and functions are often called in Kotlin

//Use the fun keyword to define a function
//methodName is the name of the defined function
//(the parameters in parentheses are the accepted parameters. Any number (can be empty). This example is two parameters of Int type) 
//Format: parameter name (optional): parameter type
//After (): Int is to declare that the function is to return Int type data
//Inside {} is the function body
fun methodName(param1: Int, param2: Int): Int{ //Standard function
	return 0

Grammar sugar

Kotlin allows us to write the only line of code at the end of the function definition without writing the function body, and use the equal sign connection in the middle

//Primitive function
fun largerNumber(num1: Int, num2: Int): Int{
	return max(num1, num2)
//The returned integer data is an integer data returned by the max function after passing in the max function. Since there is only one line, the function body is not allowed to be written
fun largerNumber(num1: Int, num2: Int): Int = max(num1, num2)

3. Logic control of program

There are three kinds of program execution statements: sequential statements, conditional statements and circular statements
Sequential statement: as the name suggests, execute code line by line in order
There are only two kinds of conditional statements, one is if statement, the other is when statement
Loop statement: as the name suggests, there are two kinds of loop statements, one is the while loop and the other is the for loop

3.1if conditional statement

fun largerNumber(num1: Int, num2: Int): Int{
	var value = 0;
	if(num1 > num2){ //If num1 is greater than num2, get num1
		value = num1
	} else { //Otherwise, get num2
		value = num2
	return value //To return the obtained number is actually to return the maximum number
//Simplified writing
fun largerNumber(nuum1: Int, num2: Int): Int{
	val value = if(num1 > num2){
	} else {
	return value
//Simplified writing
fun largerNumber(num1: Int, num2: Int): Int{
	return if(num1 > num2){
	} else {
//Simplified writing
fun largerNumber(num1: Int, num2: Int) = if(num1 > num2){
} else {
//The simplest way to write
fun largerNumber(num1: Int, num2: Int) = if(num1 > num2) num1 else num2

3.2 when conditional statement

It is similar to the switch in Java, but it does not need to add a break after each case, just write the required logic.
The when statement allows any type of parameter to be passed in, and a series of conditions can be defined in the when structure
Match value - > {execute logic}

The following is how to write the if statement

fun getScore(name: String) = if(name == "Tom"){
} else if(name == "Jim") {
} else if(name == "Jack") {
} else if(name == "Lily"){
} else {
//Concise writing, using when conditional statements
fun getScore(name:String) = when (name){
    "Tom" -> 86
    "Jim" -> 77
    "Jack" -> 95
    "Lily" -> 100
    else -> 0

The when statement allows type matching

//Number is a subclass of Int, Long, Float, Double and other number related classes
fun checkNumber(num: Number) {
    when (num) {
    	//The is keyword is equivalent to Java instanceof
        is Int -> println("is Int")
        is Double -> println("is Double")
        else -> println("not support")

How to use parameters without transmission

//Sometimes you may need to put the expression into the judgment separately, which is suitable for separate judgment
fun getScore1(name: String) = when {
    name.startsWith("Tom") -> 86 //The name begins with Tom
    name == "Jim" -> 77
    name == "Jack" -> 95
    name == "Lily" -> 100
    else -> 0

3.3 circular statements

The while method is the same as Java

//When the Boolean expression of while (Boolean expression) is false, the loop exits
//The biggest difference between while and do... while is that while judges the expression before deciding whether to loop, while do....while judges the expression before deciding whether to loop, so it should loop at least once
fun getWhile() {
    var i = 10
    while (i > 0) {
        println("i is $i")
        i -= 1
    var y = 10
    do {
        println("y is $y")
        y -= 1
    } while (y > 0)

for loop statement
Kotlin's loop statement has only a for - in loop
Simpler than for-i, but less flexible than for-i

//Interval: and includes 0 and 10, mathematical expression: [0,10]
val range = 0..10
//Interval, left closed and right open, including 0 and excluding 10. Mathematical expression: [0,10)
val range = 0 until 10

fun forIn(){
	//Output 0 - 10
    for (i in 0..10){
    //Output 0-9
	for (i in 0 until 10){
    //Cycle the number of 0-9, but increase 2 each time
    //step keyword, which is equivalent to i = i+2 in Java
    for (i in 0 until 10 step 2){
    //Flashback, 10 starts to drop to 1, and the downTo keyword can be used with step
    for (i in 10 downTo 1){

4 object oriented programming

4.1 object oriented, class and object

Like Java, Kotlin is an object-oriented language
Object oriented can create classes. A class is the encapsulation of a thing or thing into a class. The class name is usually a noun, and the class also has its own fields and functions. Fields are the attributes and functions.

Classes and objects
An object is actually an instance object of a class. In short, I define a "firewood" class (this is an animal)
"Xiao Chai" has age, name and behavior. He can eat, eat() and sleep()
Then I define a "Xiaochai" instance object, that is, I have a pet of Xiaochai. His name is Memory. He was just born and only 1 year old. He can eat() and sleep()

4.2 inheritance and constructor

In Kotlin, classes are not inheritable by default. If they need to be inherited by a class, the class must be preceded by open. In this way, the subclass can use the methods and variables of the parent class

//Inherited class
open class Person{
//Inherited class
class Student : Person(){
	//The inherited class here needs to add () because it involves the primary constructor. The primary constructor and secondary constructor are a little different from those in Java

Constructor in Java

public class Student{
	public Student(){
	public Student(int age, String name){

Kotlin's is special, which is divided into primary constructor and secondary constructor
The main constructor will be your most commonly used constructor. Each class will default to a main constructor without parameters. You can indicate its parameters. The main constructor has no function body and can be defined directly after the class name

//The Person() here is actually calling the Person constructor Person()
class Student(val sno: String, val grade: Int) : Person(){
	//init constructor and the logic of the main constructor can be written here (but this is not the best way, and it is generally not used in this way)
		println("sno is " + sno)
		println("grade is "+ grade)	

Secondary constructor
You can hardly use the secondary constructor. Kotlin provides a function to set the default value of parameters, which can basically replace the function of the secondary constructor. A class can only have one primary constructor and multiple secondary constructors. A secondary constructor can instantiate a class, but it has a function body. (that is, if you want to omit a variable, you can set the default value in the main constructor. After setting, you can use the main constructor to create it without adding the variable)

class Student(var){

When a class has both primary and secondary constructors, all secondary constructors must call the primary constructor (including indirect calls)

//The age and name here cannot be set to val because they will conflict with the age and name of the parent class. Without them, the scope is only in the main constructor
class Student(val sno:String, val grade: Int, name: String, age: Int)
    :Person(name, age) {
    //Define the secondary constructor through the constructor keyword
    constructor(name: String, age: Int):this("", 0, name, age){
    constructor() : this("", 0){

//This is the creation of a secondary constructor without a primary constructor. There is no primary constructor, so there is no need to add parentheses when inheriting Person
class Student : Person{
	constructor(name:String, age: Int) : super(name, age){

4.3 interface

The interface is almost the same as that of Java
A class can implement multiple interfaces

interface Study{
	fun readBooks()
	fun doHomework()
//Class implements interfaces, separated by commas
class Student(name: String, age: Int) : Person(name, age), Study{
	//override keyword overrides or implements an interface function
	override fun readBooks(){
		println(name + " is reading.")
	override fun doHomework(){
		println(name + " is doing homework.")

//Interface 2
interface Study{
	fun readBooks()
	fun doHomework() { //In this case, when implementing the Study interface, the doHomework() method may not be implemented. If it is not implemented, it means that the method is effective. The rewritten method shall prevail
		println(name + " is doing homework.")

4.4 modifiers

Modifier JavaKotlin
publicAll classes visibleAll classes visible (default)
privateThe current class is visibleThe current class is visible
protectedThe current class, subclass and classes under the same package path are visibleThe current class and subclass are visible
defaultClasses under the same package path are visible (default)nothing
protectednothingClass visible in the first mock exam module

4.5 data class and singleton class

In Java, data classes usually need to override the equals(), hashCode(), toString() methods
The Kotlin implementation is simple

//When the data keyword is used, the equals(), hashCode(), toString() methods will be automatically generated for you according to the parameters of the main constructor
data class Person(val country: String, val sex: String)

Method of creating singleton in Java

//Singleton creation
public class Singleton{
	private static Singleton instance;
	private Singleton(){}
	public synchronized static Singleton getInstance(){
		if(instance == null{
			instance = new Singleton();
		return instance;
	public void singletonTest(){
		System.out.println("singletonTest is called.")
//Use of singleton
Singleton singleton = Singleton.getInstance();

Method of creating singleton in Kotlin

//It's that simple. This is a singleton pattern
//You don't need to provide any method to create, just change the class keyword to the object keyword, because Kotlin will automatically help you create a Singleton instance to ensure that there is only one instance in the world
object Singleton{
	//Add a function in singleton mode
	fun singletonTest(){
		println("singletonTest is called.")
//The use method of singleton is similar to the calling method of static method in Java

4.6 lambda programming

Sets are mainly divided into three types: List, Set and Map
The main implementation classes of List are ArrayList and LinkedList
The main implementation class of Set is HashSet
The main implementation class of Map is HashMap

	//Create an ArrayList instance
	val list = ArrayList<String>()
	//Use the listOf() function to simplify initialization writing
	//However, the set created by listOf is immutable, that is, after creation, it can no longer be changed. It can only be read and cannot be changed
	val list = listOf("Apple", "Banana", "Pear")
	for(fruit in list){
	//This is the list initialization method that can be modified
	val list = mutableListOf("Apple", "Banana", "Pear")
	//The usage of Set is almost the same as that of List, except that it is changed to setOf() and mutableSetOf()
	val set = setOf("Apple", "Banana", "Pear")
	val set = mutableSetOf("Apple", "Banana", "Pear")
	//The usage of Map is quite different from that of List and Set
	//The first use of Map
	val map = HashMap<String, Int>()
	map.put("Apple", 1)
	map.put("Banana", 2)
	map.put("Pear", 3)
	//The second use of Map
	val map = HashMap<String, Int>()
	map["Apple"] = 1
	map["Banana"] = 2
	map["Pear"] = 3
	//The simplest use of Map
	val map = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4)
	for((fruit, number) in map){
		prinltln("fruit is " + fruit + ", number is " + number)

Collection's functional API

	val list = listOf("Apple", "Banana", "Pear")
	val maxLengthFruit = list.maxBy{it.length} //Get the longest fruit

Lambda expression:
{parameter name 1: parameter type, parameter name 2: parameter type - > function body}
Lambda expression. You can edit any line of code, but it is not recommended to be too long. The last line will be automatically used as the return value of lambda expression
The above is a code segment, which is reduced to one sentence because of Kotlin's characteristics

	val list = listOf("Apple", "Banana", "Pear")
	val lambda = {fruit: String -> fruit.length}
	val maxLengthFruit = list.maxBy{lambda} //Get the longest fruit
	//Simplified version
	val maxLengthFruit = list.maxBy({fruit: String -> fruit.length})
	//Kotlin stipulates that when the Lambda parameter is the last parameter of the function, you can move the Lambda expression outside the parentheses
	val maxLengthFruit = list.maxBy() {fruit: String -> fruit.length}
	//Lambda parameter is the only parameter of the function, and parentheses can be omitted
	val maxLengthFruit = list.maxBy{fruit: String -> fruit.length}
	//Kotlin derivation mechanism, String type declaration can be omitted
	val maxLengthFruit = list.maxBy{fruit-> fruit.length}
	//When a Lambda expression has only one parameter, you can use the it keyword instead
	val maxLengthFruit = list.maxBy{it.length}

The map function maps the elements in the collection to other values, and the rules are specified in Lambda

val newList ={"Code block"}

The filter function is used to filter the elements in the collection when the condition is the code in Lambda

//Keep fruit within 5 characters
val newList = list.filter{ it.length <= 5}

The any function returns true as long as one of the elements in the collection is satisfied, and false if none is satisfied
The all function returns true only if all elements in the collection are satisfied. Otherwise, it returns false as long as one element is not satisfied

//Returns true whenever the length of a fruit is less than 5
val newList = list.any{ it.length <= 5}
//false is returned as long as one fruit is not less than 5
val newList = list.all{ it.length <= 5}

4.7 using Java's functional API in Kotlin

The Java method is invoked in Kotlin, and the method accepts a Java single abstract method interface parameter, so function API can be used.
A single abstract method means that there is only one method to be implemented in the interface
Example: Runnable interface

//Runnable interface
public interface Runnable{
	void run();
//Usage of using Runnable interface
new Thread(new Runnable(){
	public void run(){
		System.out.println("Thread is running");
//Usage of Kotlin using Runnable interface
//Use the object keyword to create an anonymous class
Thread(object : Runnable{
	override fun run(){
		println("Tread is running")
//Shorthand method of functional API
//When there is only one method to be implemented, Kotlin can automatically understand that the Lambda expression inside is the implementation content of the run() method
	println("Thread is running")
//When more than one Java single abstract method interface parameter does not exist in the parameter list of Java method, we can also omit the interface name
	println("Thread is running")
//When the Lambda expression is the last parameter of the method, you can move the Lambda expression outside the parentheses. At the same time, the expression is the only parameter, and the parentheses can be omitted
	println("Thread is running")

Although we all use Kotlin to write code now, we need to deal with the Android SDK often, and it is still written in Java. For example, the listening event of Button


4.8 null pointer

I believe that when writing Android, null pointer exceptions have been removed more or less. In Java, when there may be null data, we have to judge null. Kotlin has a null checking mechanism, which uses null checking during compilation, so as to almost prevent null pointer exceptions.
However, this may make the code more troublesome, but Kotlin provides a set of tools to make it easy for us to judge null

///In this case, if you pass a null, an error will be reported when compiling because a null pointer appears
doStudy(null) //Air transmission
fun doStudy(study:Study){

In this case, we will report an error as long as we pass it empty, but sometimes we need to pass it empty, so we need a question mark. Add "null" after the data type? This means that the data can be null
Int? Represents nullable integer data String? Represents nullable data,

//At this time, there will be no error in the air
doStudy(null) //Air transmission
fun doStudy(study:Study?){

Although it can be null passed, the two methods inside will certainly report null pointer exceptions, because they must have data to execute. At this time, we can write like Java

fun doStudy(study:Study){
	if(study != null){

But if it is written in this way, it has no advantage and is very troublesome
You can use it here The meaning of this symbol means that when the object is not empty, it will be called, and when the object is empty, it will not be executed
This code is equivalent to Java

if(a != null){

It can be used in Kotlin like this Symbols to simplify code

	//a is there an object? If yes, execute the doSomething() method. If not, skip and do not execute

?: Operator. If both sides of the operator are expressions, the result of the expression on the left will be returned if the result of the expression is not empty, otherwise the result of the expression on the right will be returned.

//If a is not empty, then c = a; Otherwise c = b
val c = a ?: b
//Original writing
fun getTextLength(text: String?): Int{
	if(text != null){
		return text.length
	return 0
//use?. And?: Writing method of
//When text is empty, do not execute the length method, return a null, and then use?: Judge whether the right side is null, and return a 0 if it is,
fun getTextLength(text: String?) = text?.length ?: 0

Although there is a null pointer checking mechanism, sometimes it fails

fun main(){
	if(content != null){
//Although it is judged to be empty outside, it will re judge whether the variable may be empty inside the method, because the method does not know that it has been judged to be empty in the external main function, so it can only judge whether it is empty
fun printUpperCase(){
	val upperCase = content.toUpperCase()
//You can use force compilation Symbol, but this way of writing is risky, because we need to ensure that it will not be empty, otherwise we will report an error and flash back
	val upperCase = content!!.toUpperCase()

Let function, using the method. Here is the let function that calls the obj object, and then the code in the Lambda expression will be executed by science, and the obj object will be passed into the expression. Here, obj and obj2 are actually the same object. This function can be used in conjunction with the null checking mechanism

obj.let{ obj2 -> 
	//Write specific code

//Original code
//In fact, this is equivalent to judging if (study! = null) {} twice, each Judge once
fun doStudy(study: Study?){
//Used with let, this code means that the let function is executed as long as study is not empty
//The let function passes the study object into the Lambda expression
fun doStudy(study: Study?){
	study?.let{ stu ->
fun doStudy(study: Study?){

When the study object is a global variable, the if statement will still report an error, such as

var study: Study? = null
fun doStudy(){
	if(study != null){

But let function can deal with the problem of global empty judgment

4.9 string embedded expression

Kotlin string inline expression

// The ${} expression can kick part of the content
"hello, ${}. nice to meet you!"
//When there is only one variable, {} can also be omitted
"hello, $name . nice to meet you!"
//println("my name is " + name + ", my age is " + age)
//println("my name is $name, my age is $age")

4.10 default values of function parameters

Kotlin provides the function to set the default value of parameters
Because of this function, secondary constructors are rarely used

fun printParams(num: Int, str: String = "hello"){
	println("num is $num, str is $str")
//The second parameter of the above function is the default value, so when we use it, we can only pass one Int parameter
fun main(){
//When setting the default value for the first
fun printParams(num: Int = 100, str: String){
	println("num is $num, str is $str")
//Wrong use, this will report an error
//Can't it be used like this? No, the Kotlin mechanism also passes parameters through key value pairs
printParams(str = "world", num = 123)
printParams(str = "world")
//It is this method. Therefore, the main constructor adds multiple parameters. Different methods use the main constructor to create objects

Tags: Java Android

Posted on Thu, 14 Oct 2021 14:30:20 -0400 by Liam-PHP