Life is too short to use Kotlin

This is a more program-friendly language, which reduces the workload of developers. Many of the things that developers do can actually be done by the compiler, which is a higher level language. Java is rigorous, but it is too tedious, too verbose, a small thing but to write a lot of code, and some of the code is very mechanical, in the actual coding process are automatically generated by IDE. Java, C, C++, Object C these are the programming languages of the last century.

Now in the new era, programming has also developed a lot, like lambda expressions, functional programming, and so on some new concepts and paradigms emerge. So there are new-age programming languages like Swift for fruit, Groovy, Scala, and Kotlin for the Java camp. Kotlin is a new generation of programming language, perfect integration with Java, simple, convenient, can greatly improve the readability of programs, especially for Android developers. Swift was designed to liberate fruit developers, and Kotlin is designed to liberate Android developers.

Although Kotlin can be used anywhere Java can be used, there are currently two main areas of application development, server and Android, especially with official support from Google, so Kotlin’s significance for Android developers is even greater. As an Android monkey, Be sure to learn this modern programming language, because when you do, you’ll realize that all the code you’ve written has been a waste of your life.

Development environment setup

There are three ways

The command line

In fact, this is the best way, because it is very easy to configure. Go to the official website to download the compiler, unzip it, and put kotlinc/bin/ in the PATH environment variable. If you want to configure Vim, also need to install the plug-in, the big god has already put the plug-in ready, just need to download, and then install according to the official method, in fact, is to decompress the thing copy to the corresponding directory inside good.

Idea IntellJ

This is to see the official document can, lonely not pro test, if you encounter difficulties please Google.

Android Studio

Because Kotlin has support for Android Studio, and Google has support for Android Studio, you can use Kotlin directly in Android Studio. As a result, versions of Android after Stuido 3.0 require no special configuration to use the Kotlin case.

For those who are just starting to learn Kotlin, it is recommended to use the command line instead of using Android Studio, especially to directly create an Android project based on Kotlin, because at this time, the language is not familiar enough, directly to the project, will get lost in the project configuration. Frameworks and language base. When you first learn a language, you need to learn the basic syntax and features of the language itself, which is best to bypass the framework and project first. It will be easier to get started.

Hello world

This is a must-learn course for all programming languages. The purpose is to give learners a quick taste of a language. We don’t have to think about it, just type in the example letter by letter:

  1. Choose your favorite text editor, such as Vim hello.kt, Kotlin’s file extension is *.kt, and we’ll just follow it.
  2. Type it in verbatim:

One, two, three, four, fiveCopy the code
package hello

fun main(args: Array<String>) {
    println("Hello, world")
}
Copy the code

Go back to the command line, compile the source code, and if all goes well you get a file called hello.jar, which is kotlin’s final output and its target file.


1
Copy the code
kotlinc hello.kt -include-runtime -d hello.jar
Copy the code

Kotlin will compile a standard Jar file and run it just like any other Jar file:


1
Copy the code
java -jar hello.jar
Copy the code

You’ll get Hello, world so that’s it, the first Kotlin program is done, isn’t it cool, and I can’t wait to learn more about it! Read on.

The basics

Sentence structure

How much time can you save by having one statement in a row (regardless of the difference between statement and expression), no semicolons, no scoring signs? Does it feel like life is wasted on semicolons? If you want to write more than one statement on a single line, prefix it with a semicolon.

Indentation rules are the same as in Java, with four Spaces, you can use TAB, or no indentation, as long as no one hits you.

Statement blocks need curly braces {}. In short, the statement structure is very similar to Java.

variable

Var is used to declare variables and val is used to declare constants. Because Kotlin is a statically strongly typed language (that is, every variable must know its type at compile time), you need to declare a type by following the variable name with a colon and a space to match the type name, much like Pascal. If you declare the expression directly, you do not need to specify the type, and the compiler will infer its type from the definition expression. Example:


1
2
3
Copy the code
var str: String
val i: Int
var str = "Hello, world"
Copy the code

Statements and expressions

An expression has a value and can be placed to the right of an assignment, while a statement has no value and cannot be placed to the right of an assignment

Basic operation

Without further ado, just like Java

annotation

This is the same as Java: // single-line comments // multi-line comments /* / documentation

function

Function name (argument): return type {function body}, as in:


1
2
3
Copy the code
fun foo(name: String): Int {
   return name.length()
}
Copy the code

Name parameters and default values. You can call a function with the names of the parameters to increase readability. You can use default values when declaring functions to better support function overloading. Such as:


1
Copy the code
fun foo(name: String, number: Int = 42, toUpper: Boolean = false): String {}
Copy the code

When used, you can specify the name of the argument:


1
2
3
4
Copy the code
foo("a)
foo("b", number = 1)
foo("c", toUpper = true)
foo(name = "d", number = 2, toUpper = false)
Copy the code

If a function has only one expression and a return value, place the return value after the function, for example:


1
Copy the code
fun foo(name: String): String = name.toUpperCase()
Copy the code

You can even omit the return type declaration, for example:


1
Copy the code
fun foo(name: String) = name.toUpperCase()
Copy the code

Unlike Java, Kotlin’s functions can be declared toplevel, which is the same level as class, which means they don’t have to be inside a class, which is similar to C and C++. In addition, a function can be assigned to a variable just like any other variable.

Classes and objects

Class declaration and object creation

Use class to declare a type, use: to inherit a parent class or implement an interface, and do not use new to create objects:


1
2
3
4
Copy the code
class Person {
   var name: String
   var age: Int
}
Copy the code

If a class is empty and has no content, then the curly braces {} can be omitted:


1
Copy the code
class Person
Copy the code

Create an object:


1
Copy the code
var someone = Person()
Copy the code

Primary constructor

Constructors, known as primary constructor, can be written directly after the class name:


1
Copy the code
class Person constructor(name: String)
Copy the code

4. In general, constructor can be omitted:


1
Copy the code
class Person(name: String)
Copy the code

Since primary Constructor does not contain code, you can use the Initializer block to do some initialization work, or you can use the initializer block to define attributes:


One, two, three, four, five, sixCopy the code
class Person(name: String) {
    var firstName: String = name
    init {
        println("First initializer block that prints ${name}")
    }
}
Copy the code

In general, a more concise expression can be made if the declared attribute variable has an assignment from primary Constructor (via the Initializer block) :


1
Copy the code
class Person(var name: String, var age: Int)
Copy the code

This is equivalent to:


1
2
3
Copy the code
class Person(theName: String, theAge: Int) {
   var name: String = theName   var age: Int = theAge
}
Copy the code

If primary construct is preceded by a property declaration or annotation, the keyword constructor cannot be omitted:


1
Copy the code
class Person public @Inect constructor(var name: String)
Copy the code

Secondary constructor

What if Primary Constructor does not meet the requirements? You can also declare other constructors, called secondary constructor:


One, two, three, four, fiveCopy the code
Class Person {var name: String constructor(name: String) {this.name = name}}Copy the code

… class = ‘class1’ > Primary constfuctor and Second constructor can be used together:


One, two, three, four, fiveCopy the code
class Person(var name: String) {
    constructor(name: String, parrent: Person) : this(name) {
        parrent.addChild(this)
    }
}
Copy the code

Delegate the secondary construct as delegate as possible to primary constructor. This delegate means that the primary constructor will be executed before second constructor. Initiailzer blocks are executed in primary Construct, which ensures that initiliazer blocks are executed before Second Constructor. Even if no primary constructor is declared, the compiler generates a default primary constructor and assigns the secondary constructor’s default delegate to the primary constrcutor. That is, the Primary Constructor and initializer block are guaranteed to be executed before Second Constructor:


12 3 4 5 6 7 8 9 10 11 12 13Copy the code
class Constructors {
    init {
        println("Initializer block")
    }

    constructor(i: Int) {
        println("second constructor")
    }
}

fun main(args: Array<String>) {
    val c = Constructors(3)
}
Copy the code

Output:


1
2
Copy the code
Initializer block
second constructor
Copy the code

Property and access methods

Kotlin generates default setters and getters for declared properties:


One, two, three, four, fiveCopy the code
class Person(var name: Strring, var age: Int val p = Person("Kevin", 24) p.get_name () // returns "Kevin" p.age (32) // age becomes 32Copy the code

If you want to customize setters and getters, you can:


12 3 4 5 6 7 8 9 10 11 12 13 14 15 16Copy the code
class Person {
    var name: String
        set(n: String) {
            if (n == null || n == "") {
                name = "Unkown"
            } else {
                name = n
            }
        }
        get() {
            if (name == "Unkwon") {
                return "Nobody"
            }
            return name
        }
}
Copy the code

Define the methods of the class

Just like declaring a normal function, but inside a class:


1
2
3
Copy the code
class Person(val name: String, val age: Int) {
    fun report() = "My name is $name, and I'm $age"
}
Copy the code

If you want to override a method of a parent class, you need to add the Override keyword to the method declaration.


1
2
3
Copy the code
class Doggy(val name: String) : Animal {
    override fun yell() = "Barking from $name"
}
Copy the code

Access permissions

Access permissions are also similar to Java: public, protected, private, and internal. The first three meanings are the same, but the default values are different. In Java, if the member is not specified, it is package scope, which means that the same package can be accessed. But Kotlin is public by default.

Internal is visible within a module, similar to package in Java, but unlike package, module definition is a set of Kotlin files that are compiled together. It is related to compilation and packaging.

Then there are classes, which by default are non-inheritable, equivalent to final classes. If you want to allow inheritance you declare the class with open.

string

The concept is not said, most of the same as Java, like supported methods and so on. The only thing that needs to be said about string templates is that there is a more convenient way to convert other types to strings than in Java: insert variables directly into strings using $, as in:


1
2
3
4
Copy the code
Val MSG = "Error 1" val count = 32 print("We got message $MSG"  Total is 32Copy the code

Lambda expressions

I’m going to start with the concept of a higher-order function, which is a function that takes another function as an argument, or that produces a function, that is, a function that returns a value. As mentioned earlier, functions are first-class objects and can be used like regular variables, so higher-order functions can be used as arguments or return values. Lambda expressions are designed to make higher-order functions easier to use.

Lambda expressions

As the programming language of the new era, all support functional programming, and lambda expression is an essential part of functional programming. What is a lambda expression? The simplest way to say it is a function without a name, very short, usually a sentence or two without a name. {A, B -> C} {A, B -> C}


1
Copy the code
Val sum = {x: Int, y: Int -> x + y}Copy the code

Where, the type of the argument can be omitted because the compiler can infer from the context: Max (strings, {a, b -> a.length < b.length} expression part, can be more than one, the last expression as the return value.

When passing a lambda expression as the last argument to a function, we can write the lambda expression directly outside the argument, for example:


1
Copy the code
val product = items.fold(1) { acc, e -> acc * e }
Copy the code

When lambda is the only argument, we can omit the parentheses:


1
Copy the code
run { println("Hello, world") }
Copy the code

Alternatively, if a lambda expression has only one argument, the argument can be omitted and the expression written directly:


1
Copy the code
eval{ x * x }
Copy the code

Function types

As mentioned earlier, a function is a first-class class that can be used just like a normal variable, that is, it is a type. It takes the form (A, B)->C, where parentheses are arguments and C is the return type, as in:


1
2
Copy the code
val sum: (Int, Int)->Int = { x, y -> x + y }
val square: (Int)->Int = { x -> x * x }
Copy the code

The reason for mentioning function types is that higher-order functions sometimes need to be declared:


1
2
Copy the code
fun walk(f: (Int)->Int)
fun run(f: ()->Unit)
Copy the code

Unit is a special return value, equivalent to void, meaning that this function has no return value.

A collection of

In fact, most of it is the same as Java. There are only some functional operations, we should pay more attention to use, so as to make the code more concise, such as:

  • traverse
  • filter
  • mapping
  • The sorting
  • folding
  • grouping
  • classified

These operations, for everyone should be easy to understand, not an explanation, to break the code to know:


12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24Copy the code
fun collectionTests() { val list = listOf("Apple", "Google", "Microsoft", "Facebook", "Twitter", "Intel", "QualComm", List.foreach {println(it)} // Filter by condition, Filter {it. Length < 6} println(short) // [Apple, Intel, Var lenList = list.map{it. Length} println(" length of each item $lenList") //Length of each item [5, 6, 9, 8, 7, 5, 8, 5] // Get Sorted by length by order = list.sortedby {it. Length} println("Sorted by length $ordered" [Apple, Intel, Tesla, Google, Twitter, Facebook, QualComm, Microsoft] Val joint = list.fold("", {partial, item -> if (partial! = "") "$partial, $item" else item }) println("Joint list with comma $joint") // Joint list with comma Apple, Google, Microsoft, Facebook, Twitter, Intel, QualComm, Tesla Divide the list into two groups with some condition val (first, second) = list.partition { it.length < 6 } println("Length shorter than 6 $first") // Length shorter than 6 [Apple, Intel, Tesla] println("Longer than 6 $second") // Longer than 6 [Google, Microsoft, Facebook, Twitter, QualComm] By grouping elements in a certain way, Var bucket = list.groupby {it.length} println("$bucket is a Map now") //{5=[Apple, Intel, Tesla], 6=[Google], 9=[Microsoft], 8=[Facebook, QualComm], 7=[Twitter]} is a map now }Copy the code

Null processing

To reduce Nullable exceptions, Kotlin added the Nullable type. The core principle is as follows: when declaring a type, you must explicitly tell the compiler whether the variable can be null. If it can be null, you can assign it to the variable and check whether it is null when using it. You cannot assign NULL to a variable if it cannot be null. That is, the compiler does some checking to reduce nullPointerExceptions.

Nullable variables

The default variable declaration is not null, for example:


1
2
Copy the code
Var safe: String safe = null // Compile Error is generatedCopy the code

To allow a variable to be null, add a question mark after the type to tell the compiler that it is a nullable type:


1
2
Copy the code
var danger: String?
danger = null // OKay
Copy the code

Nullable cannot be used directly and must be checked for null:


1
2
Copy the code
safe.length // okay
danger.length // compile error, danger could be null
Copy the code

Check Nullable for authenticity

You can do it the old-fashioned way:


1
Copy the code
val len = if (danger ! = null) danger.length else -1Copy the code
Safe call

Since there is a Nullable type, there are ways to make it easier to use:


1
Copy the code
val len = danger? .lengthCopy the code

Danger returns null if danger is null, otherwise the length is Int. (Another Nullable type). This can also be chained:


1
Copy the code
bob? .department?.head?.nameCopy the code

If either ring is NULL, null is returned. Does it feel like it saves a lot of judgment if (a == null)?

Elvis operator

What if you cannot accept null returns from the Safe Call? Want to provide default values? There are also ways:


1
2
Copy the code
val len = danger? .length println(len ? : 1)Copy the code

A little twist. First of all, Danger? .length returns an Int? Right, then? The: () function returns -1 if len is null, otherwise returns its value.

Mandatory value!!

If a Nullable variable is null, a NullPointerException is thrown. If a Nullable variable is null, a NullPointerException is returned.


1
Copy the code
val len = danger!! .length // get length or NullPointerExceptionCopy the code

Although the compiler can help us do some things, a large number of Npes in real projects do not come directly from null assignments that can be easily traced, but mostly occur in multithreaded environments and very complex logic, and it remains to be seen whether the compiler can track and alert us. In addition, it is up to the engineers’ design skills to determine when nulls are allowed and when nulls are not, such as returning empty lists, maps, or strings as much as possible, rather than simply returning NULL, which can reduce NPE.

Exercises

Just reading books or watching tutorials is boring. The most important thing to learn programming is to get started and practice, so as to deepen the impression and better understand the concepts and knowledge points in books or tutorials. There is also a very good training program called Kotlin-Koans, which is perfect for beginners. Here’s how to use this exercise:

  1. Go to the official website to download, unzip
  2. Open the project with Android Studio and answer yes to all prompts
  3. To run the test, you need to compile the project first, otherwise it will prompt you that you cannot find the base test class. Go to the Gradle window, usually on the right, and click open to go to Kotlin-koans ->Tasks-> Build -> Build, and run it
  4. In the Project view, you can see the Kotlin-Koans Project. There are two subdirectories in the kotlin-Koans Project, one is Java, and the other is tests. The subdirectories in the two directories are one by one. Then edit the Java/corresponding code below until the test passes.

Essence of Kotlin

Thus, we can see that the core concept of Kotlin’s language design is simplicity, which is a core concept of Kotlin, so we can see that some mechanical, repetitive, and can be inferred from the context can be omitted to increase readability. This is what we want to do with Kotlin, to make the most of the language. Brevity, of course, is not to shorten code at the expense of readability, but to use standard brevity in the language, such as lambda expressions, omitted arguments, and so on.

Be careful to refer to Kotlin Conventions and Android Kotlin Conventions to write more concise and easy-to-understand code.

Android dev setup

Let’s create a new project to implement a Hello, World Android application using pure Kotlin to show how to use Kotlin in Android:

Note: This is Android Studio version 3.1.2, which supports Kotlin by default. If you want to use a version smaller than 3.0, you need to install Kotlin.

  1. Creating a project is the same process as creating a normal Android Studio project. As of Android Studio3.0, when creating a project, there will be a Checkbox asking you if you want to add Kotlin. I’m going to select it here.
  2. Just go straight to the next step
  3. Next, create an Empty Activity
  4. Finish

  5. The layout is just like any other new Android project
  6. The code is already Kotlin’s
  7. Saying “Hello, world” is a little boring, so add a click event:

12 3 4 5 6 7 8 9 10 11 12 13Copy the code
class HelloActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_hello)

        val colorTable = listOf("#ff0000", "#00ff00", "#0000ff", "#ffff00", "#00ffff", "#ff00ff")
        val label = findViewById<TextView>(R.id.label)
        label.setOnClickListener { view ->
            val randomIndex = (Math.random() * colorTable.size).toInt()
            view.setBackgroundColor(Color.parseColor(colorTable[randomIndex]))
        }
    }
}
Copy the code

In fact, overall, the layout and project structure is the same as Android, with the only difference being that the code can now be written in Kotlin.

Good to go

At this point, you are ready to use Kotlin to build applications or apply Kotlin in your projects.

References and useful information sharing

  • The official documentation
  • Awesome Kotlin Resources
  • Kotlin and Android
  • Resources to Learn Kotlin
  • Learn Kotlin in Y minutes