1. The background

Jetbrains launched Kotlin back in 2010, and at Google’s I/O Developer conference on May 18, 2017, it was announced that Kotlin will be a level 1 programming language for Android development. This lovely language works seamlessly with Java. I’ve been doing C# and python development for a while, and I feel like all three are very similar to each other. It’s not clear who is copying whom and who is eating whose syntactic candy.

2. Differences and contrasts

2.1 the constructor

java Kotlin
The constructor The main constructor
Once the constructor
  • Java version:
public class Model {

    public Model(){}

    public Model(String name){}
}
Copy the code
  • Kotlin version:
    • The main constructor
Class KtModel constructor(name: String) class KtModel constructor(name: String)Copy the code

With the advent of Kotlin’s master constructor writing, javabeans in Java can be simplified, keyword: data

data class KtModel(var id: Int, var name: String)
Copy the code
  • Kotlin version
    • Once the constructor
class Model{ var mName:String? Class Model{var mName:String}} class Model{var mName:String? = null constructor(name:String,age:Int = 0){mName = name}}"Inke"Kotlin supports @jvmoverloads to load the Java constructor class Model{var mName:String? {mName = name}} //"Inke", 20); Model model = new Model("Inke");
Copy the code

2.2 Customizing setters and getters

Javabeans declared by data implement getters by default, as well as if the variable is of type var, and methods like equal() hashcode() toString() are automatically overwritten. Custom setter and getter methods are also supported, written the same way as in c#.

class Student(var name: String, var grade: Int) {// Kotlin enum enum class LEVEL {GOOD, JUSTSOSO} var LEVEL: LEVEL =if (grade > 90) LEVEL.GOOD else LEVEL.JUSTSOSO
        set(value) {field = value} get() = field} ps: represents by fieldsetGet the properties of theCopy the code

2.3 Condition Screening

To filter a field type based on different values in Java, use the same Switch “statement” as:

switch (itemViewType) {
            caseITEM_VIEWTYPE_LINKMSG:// Link message with link fieldreturn new LinkMsgViewHolder(inflater);
            caseITEM_VIEWTYPE_TEXTMSG_BYME:// Own text messagereturn new TextMsgByMeViewHolder(inflater);
            caseITEM_VIEWTYPE_TEXTMSG_BYOTHER:// Someone else's text messagereturn new TextMsgByOtherViewHolder(inflater);
            caseITEM_VIEWTYPE_PIC_MSG_ME:// Own picture messagereturn new PicMsgByMeViewHolder(inflater);
            caseITEM_VIEWTYPE_PIC_MSG_OTHER:// Other people's picture messagesreturn new PicMsgByOtherViewHolder(inflater);
            caseITEM_VIEWTYPE_AUDIO_MSG_ME:// Own voice message... }Copy the code

Kotlin filters when for a field type, but it’s not a statement, it’s an expression, really an expression.

Fun getWeekInfo(day: Int): Stringreturnbehindreturn when (day) {
        1, 2, 3, 4, 5 -> "Working day"6, 7 - >"Weekend"
        else -> "unknow"Fun getWeekInfo(day: Int) = when (day) {1, 2, 3, 4, 5 -> fun getWeekInfo(day: Int) {1, 2, 3, 4, 5 ->"Working day"6, 7 - >"Weekend"
        else -> "unknow"// Java default cannot,elseMust be written, unless sealed class may not be written, as discussed later. }Copy the code

Is that all there is to it? No! high energy alert

fun getWeekInfo(student: Student) = when {
    student.name.equals("马云") - >"What a test!
    student.grade >= 60 -> "Pass"
    student.grade < 60 -> "fail"
    student is Student -> "Is equivalent to instanceof"
    else -> "unknow"} return Boolean ();} return Boolean ();} return Boolean ()Copy the code

2.4 Cycle Structure

language The number of iterations Object pool iteration
java support support
kotlin Strong support support

Java version of the two ways to write a loop

for (int i = 0; i < 10; i++) {
        //TODO
    }

for (String arg : args) {
        //TODO
    }
Copy the code

Kotlin version, written similarly to Python

// Number of iterationsfor(i in1.. 10){// the interval [1,10] is traversed upwardprint(i)
    }

for(i in10 downTo 1){// [1,10] traverses downprint(i)
    }
    
for(i in1 until 10){// [1,10print(i)
    }


for(i in1.. Step 2){// Set the number of steps to go upprint(I)} // Object pool iterationfor (arg in args){
        print(arg)
    }
Copy the code

2.5 Introduce static methods

The purpose of introducing static methods:

java Kotlin
Utility methods The expansion of the class

Introduction method:

  • java: import static com.meelive.ingkee.base.utils.guava.Preconditions.checkArgument;
  • Kotlin: import com.inke.utils.showToast

Static method of writing

  • Java: Pure utility class writing
  • Kotlin:
fun Context.showToast(message: String) : Toast { var toast : Toast = Toast. MakeText (this, the message, Toast. LENGTH_SHORT) Toast. SetGravity (Gravity CENTER, 0, 0) Toast. The show ()returnAs an extension of the Context class, toast} can be used directly in activities and services, so that the object-oriented encapsulation is more strict (personal view).Copy the code

2.6 Type Conversion

Java for type conversion, write the following statement:

Person p = new Person();
if(p instanceof Student){
    Student student = (Student) p;
    String id = student.uid;
}
Copy the code

Then check out Kotlin’s parody:

val p = Person()
if (p is Student) {
    val student = p as Student
    var uid = student.uid
}
Copy the code

Stare at the simplified version and find a different time!

val p = Person()
if(p is Student) {var uid = p.id} is (p is Student) {var uid = p.id} isCopy the code

2.7 the singleton

  • Java version singleton (lazy and hungry), lazy as follows:
public static RoomManager ins() {
    return SingletonHolder.INSTANCE;
}

private static class SingletonHolder {
    private static final RoomManager INSTANCE = new RoomManager();
}
Copy the code
  • Kotlin version
class AppManager private constructor(var info: String) {
    companion object {
        private var INSTANCE: AppManager? = null
        fun getInstance(info: String): AppManager {
            if (INSTANCE == null) {
                synchronized(AppManager::class.java) {
                    if (INSTANCE == null) {
                        INSTANCE = AppManager(info)
                    }
                }
            }
            return INSTANCE!!
        }
    }
    
    fun getPhoneInfo(arg: String): String? {
        return null
    }
}
Copy the code

If it’s a no-parameter singleton, there’s a simpler way to write it

/**
 * Created by YangLang on 2017/7/29.
 */
object AppManager {

    fun getPhoneInfo(arg: String): String? {
        return null
    }
}
Copy the code

2.8 Regular Expressions

  • Java write
String info = "12,34,56.789";
String[] split = info.split("[and]");
for(String s : split) { System.out.println(s); } Java uses re to cut by defaultCopy the code
  • Kotlin writing
 var info = "12,34,56.789"
    for (s in info.split(",".".") {println(s)} kotlin does not use regex by default","or"."Divide it up. Info.split ()".") 1. Output is null in Java because. Is the wildcard 2 in the regular rule. In kotlin, the output is 12,34,56, and 789, since kotlin doesn't use regex by default, so. It's just a regular character.Copy the code

2.9 Nested and inner Classes

Note: A nested class does not contain references to an external class, while an inner class has references to an external class. Because of this, it can also cause memory leaks when an Activity is not released.

  • java
Public class Outter {// contains a reference to the Outter class, can use the Outter method class Intter{} // does not contain the Outter class reference, Static class NotIntter{}}Copy the code
  • Kotlin
class Outter {

    inner class Intter

    class NotIntter
}
Copy the code

Java defaults to internal classes, and Kotlin defaults to nested classes, somewhat to avoid unintended memory leaks.

2.10 sealed class

The concept of sealed classes is the same as C# in that sealed classes can be inherited, but cannot themselves be instantiated. All subclasses must be in the same file, which is equivalent to encapsulating all the subclasses of the sealed class together, and can be used with when.

sealed class BaseModel{}
class FirstModel:BaseModel(){}
class SecondModel:BaseModel() {}Copy the code
fun justDo(baseModel: BaseModel) = when(baseModel){
    is FirstModel -> ""
    is SecondModel -> ""} not in useelseIf you create a class that inherits baseModel during the writing process, the "when" error will be reported directly. This feature of the sealed class ensures that when writing the expression, every case can be taken into account without any mistakes, and the code is constrained.Copy the code

2.11 the agent

Agency mode \ language java Kotlin
Static agent Square root Square root
A dynamic proxy Square root Square root
The property broker x Square root
Standard agent x Square root

This is not about Java design mode, mainly focus on Kotlin’s proxy mode, from the class proxy, attribute proxy, standard proxy three aspects

  • Class representative

If we need to create an instance of AnimatorListener, the most common way in Java is probably an anonymous inner class. We need to override its four methods, although we don’t use all of them, making the code redundant. Kotlin can use this interface to get an implementation class to override it and handle its own TODO.

class MyAnimatorListener(var animatorListener: Animator.AnimatorListener):Animator.AnimatorListener by animatorListener{ override fun onAnimationEnd(animation: Animator?) {/ / TODO can preprocess animatorListener. OnAnimationEnd (animation)}} To the needs of interface Animator. AnimatorListener AnimatorListener implemented by the incoming parameters, the MyAnimatorListener also by keyword by, will need to implement the method makes AnimatorListener, Methods can be preprocessed by overloading them.Copy the code
  • The property broker

When you modify a property with val, the property is unmodifiable and the proxy class inherits ReadOnlyProperty< proxied class, type > class

Properties can be modified when var modifiers are used. Proxy classes inherit ReadWriteProperty<Water,Boolean>

/**
 * Created by YangLang on 2017/7/29.
 */
fun main(args: Array<String>) {
    var p = Person("inke", 21)
    println("Adult or not:${p.isAdult}")
}

class Person(var name: String, var age: Int) {

    var isAdult: Boolean by isAdultProperty()
}

class isAdultProperty : ReadWriteProperty<Person, Boolean> {
    override fun setValue(thisRef: Person, property: KProperty<*>, value: Boolean) {
    }

    override fun getValue(thisRef: Person, property: KProperty<*>): Boolean {
        return thisRef.age > 18
    }
}
Copy the code
  • Standard agent

Kotlin standard agents have lazy(), Observable (),notNull().. All of these Kotlin self-built agents are in the delegates class, mostly lazy lazy evaluation in Java using suppliers and suppliers, in Kotlin the method lazy is evaluated directly, faster and stronger!!

class InfoConfig {
    val info: String by lazy {
        "Inke info"
    }
}

fun main(args: Array<String>) {
    print(InfoConfig().info)} The first time the info value is obtained, it is evaluated by the function parameter passed in by the lazy function.Copy the code

2.12 Initial value assignment of attributes

The attribute, whether declared as val or var, must be given an initial value. We are forced to write var info:String? = null. In practice, however, some attributes do not allow meaningless initial values such as NULL. I have summarized three ways to handle this (which may not be comprehensive) :

  • Lateinit var info: String(only for var types)
  • Class Student(var name: String, var age: Int){val isAudit = age > 18} class Student(var name: String, var age: Int){val isAudit = age > 18}
  • Val info: String by lazy {“Inke info”} (only for val types)

2.13 Outline of lambda (Object References, Array usage)

Use lambda expressions to create function “morphs”

 var add = { x: Int, y: Int -> x + y }
 print(add (1, 2))Copy the code

History of lambda

/ / 1. An anonymous inner class rb_home. SetOnClickListener (object: the View. An OnClickListener {override fun onClick (v: the View? {}}) // 2. If there is only one method in the inner class, shorten it to lambda expression rb_home.setonClickListener ({v -> Unit}) // 3. If the last argument to a function argument is a lambda expression, you can extract rb_HOME outside the parentheses of the function argument.setOnClickListenerRb_home. SetOnClickListener {v -> Unit} // 5. Rb_home. setOnClickListener{Unit} <==> rb_home.setOnClickListener{//TODO} if lambda expression parameters are used, omit rb_home.setOnClickListener{//TODO}Copy the code

We can define our own function according to the above ellipsis principle. In Java, we would write:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    webSettings.setAllowUniversalAccessFromFileURLs(true); } This is not flow writing, and not easy to reuseCopy the code

Kotlin can define functions like this

inline fun UP_VERSIONJELLY_BEAN(function: () -> Unit){
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEA){
        function()}} when used, you can write UP_VERSIONJELLY_BEAN{//TODO} without hesitation:Copy the code

2.14 Quality improvement in reflection

public class Test<T> {

    public Test() {}}Copy the code

In the Java runtime, the type of T cannot be determined due to type erasers. It is difficult to obtain the bytecode object of this object. However, in the earlier two days, I saw that Guava supports the runtime to obtain generic types through the TypeToken utility class. But Kotlin can easily fix this problem by tagging the keyword reified.

  • TypeToken
  • Reified is used
inline fun <reified T: Activity> Activity.newIntent() {
    val intent = Intent(this, T::class.java)
    startActivity(intent)
}
Copy the code

2.15 Let apply run with

Portal address