In 2017, Google began to promote Kotlin as the preferred language for Android development. Now it is 1202, and many friends still use Java as the development language. Their understanding of Kotlin is still stuck in the judgment of null pointer. I felt the need to reassure them about why I chose Kotlin as my preferred development language.

Kotlin’s Advantages over Java:

Compile – time nulling mechanism

Kotlin helps us avoid the vast majority of null-pointer exceptions by making mandatory judgments about where null-pointer exceptions might occur during compilation. This is mainly reflected in the fact that when we declare a variable or parameter, we must display whether the given variable or parameter can be null. Such as:

 class User {
     fun sayHello(who: String) {
         println("Hello $who")}}var user : User? = null // Declare a nullable user variable
Copy the code

Declare the user variable by following the user type with ** “? ** to indicate that the user object is potentially null, and if we use user without nullating, the compiler will throw an exception.

user.sayHello("Mark") // Using the user object directly cannot compile
Copy the code

The error is as follows:

Only safe (? .). or non-nullasserted (!! .). calls are allowed on a nullable receiver of type User?Copy the code

To use a potentially empty object, there are two options:

user? .sayHello("Mark") // Object after "? ", indicating that the sayHello method will be executed if the user object is not empty
/ / oruser!! .sayHello("Mark") // Enforce that user is not null. NullPointException is thrown when user is null
Copy the code

If we declare variables or parameters without the **”?” ** indicates that the object cannot be empty. The variable is declared as follows:

var user : User = User() // We cannot assign user to null because user cannot be null
/ / or
lateinit var user : User // Delay initialization of user by declaring user first
Copy the code

Note: If you use LateInit to delay the initialization of an object, be sure to initialize it first before using it, otherwise an exception will be thrown:

kotlin.UninitializedPropertyAccessException:lateinit property user has not been initialized
Copy the code

These are null judgments in variables, and the same is true for arguments:

fun somebody1(user : User?).{} // Allow the passed user argument to be null
fun somebody2(user : User){}  // The user argument passed in is not allowed to be null
Copy the code

Remember, in Kotlin, User and User? Are two different types, so User is passed in somebody2? Type, will not compile. Because of this, nullPointExceptions can be exposed at compile time, helping us avoid the vast majority of NullPointExceptions.

That’s Kotlin’s approach to avoiding null Pointers.

Friend: That’s it? I’ll add a few more if(user! = null) why learn a new language?

Migrant worker: Don’t worry, Kotlin is more than that, just listen to me.

Optional and named parameters

Overloading is one of the things that we see a lot in development, but how do you reload methods when you’re using Java?

public void sayHello(String name){
  sayHello(name,null.null.null)}public void sayHello(String name,Integer age){
  sayHello(name,age,null.null)}public void sayHello(String name,Integer age,Integer tall){
  sayHello(name,age,tall,null)}public void sayHello(String name,Integer age,Integer tall,String interest){
  //balabala
}

Copy the code

This is a common overloading, but if you want to override a method that takes only name and TALL parameters, how do you override it?

Kotlin’s method overloading is much cleaner than Java:

// Give age, tall, interest respectively
fun sayHello(name:String,age:Int? = null,tall:Int? = null,interest:String? = null){
	//balabala
}
Copy the code

This method variant implements the functionality of the above four methods, and has been inadvertently enhanced. If you have the embarrassing problem of name and tall, just use the named call method.

sayHello("Mark".18.180."Great Sword") // All parameters are passed in
sayHello("Mark".18) // Name and age are passed in
sayHello("Mark",age = 18) // the age parameter is specified
sayHello("Mark",tall = 180) // Name and TALL are passed in
sayHello("Mark",interest = "Great Sword") // Direct large swords are also available
Copy the code

Does it satisfy and enhance the functionality of multiple Java overloaded methods?

One thing to note, though: If the optional parameters passed in are continuous, Kotlin can deduce the type of parameter, but if not, it needs to specify which parameter to pass in the form of the appliance name parameter.

The same applies to overloading of constructors.

Function as argument or return value

Although JDK 1.8 does support passing functions as arguments, it is rarely used in projects. For what reason, I’m not sure. The Java implementation is not discussed here, but how this feature is used in Kotlin.

We now implement one of the simplest function parameter methods and discuss usage scenarios.

fun launch(block : () -> Unit){
	//do something
}
Copy the code

In the above code, we define a method called launch, which takes a function with no parameters and no return value, passing in the specific function when the method is called.

If the function argument is the last one defining the method, the function body can be written outside the parenthesized expression. If there are no arguments inside the parenthesized expression, the parenthesized expression can be omitted, so the launch method can be called as follows:

launch{
	// This is the implementation of the function argument
}
Copy the code

As abstract as it may seem, we can describe a requirement and then implement it to make sense.

Requirements:

A and B are responsible for their respective operation logic to process m and N data respectively, but the final result of processing needs to be displayed in the show method. Of course, we can use if else logic to realize the show method, pseudo-code is as follows:

fun show(m,n){
  int v = if(A){// If A is processing, return m+n
     m+n
  } else if(B){// If B is processing, return m-n
     m-n
  } 
	showIt(v) // Final processing of the result
}
Copy the code

This is all well and good, but what if a dozen people want to implement their own logic? It’s going to go to if else hell. Also, if the show method is defined in the base module, A and B are business module, the business logic module of the precipitation to the base module is unreasonable, in this kind of demand is often encountered in the Java will consider object-oriented, out of the base module interface, the interface in the A and B do the implementation, but the implementation is too complicated, Can we write it like this:

// The basic block function takes two arguments of type Int and returns an Int
fun show(m:Int,n:Int,block : (m :Int.n:Int) - >Int){
  showIt(block(m,n))
}

/ / A module
var blockA = fun (m :Int, n:Int){
  return m+n
}
show(m,n,blockA) //A's module calls the show method of the base module

/ / B module
var blockB = fun (m :Int, n:Int){
  return m-n
}
show(m,n,blockB) //B's module calls the show method of the base module
Copy the code

Is it much cleaner than abstracting into interfaces?

Another common scenario for function arguments is to replace Callback. As a Java programmer, you have to fight Callback hell every day, as evidenced by the popularity of RxJava.

We usually get the results of asynchronous methods through Callback, but we’re not going to give you an example of how to simplify the Callback hell by using interface parameters.

// Define an asynchronous method
fun asyncExecute(param:Any,result:(data:String) - >Unit){
  var result = //balabala asynchronous processing operation
  // Balalba cuts back to the main thread
  result(data)}// call the asynchronous method and show the result
asyncExecute(param){data ->
  showData(data)}Copy the code

From a code look and feel perspective, not too friendly!

A function can also be used as a return value as well as as an argument:

fun testMethod(a) : (str : String) -> Int{
	return { str ->
    str.length
  }
}
Copy the code

The above code defines a return value as a function that takes a String argument and returns an Int. However, function as the return value of the scene, I have not used the basic, have used friends can introduce experience ~

Fourth, expand the function

Capitalists: small dozen, add a method to our String helloWorker method, call this method can print “workers, workers soul, workers are people! “This sentence.

Migrant worker :(… What stupid need..) Well, all WE need to do is rewrite String to add this method, and we’ll have our own String.

Capitalist: Rewrite the String method? You go to finance to get next salary, need not come tomorrow!

Since String is final, we can’t rewrite the class to add new methods to it. Normally, String operations are handled using static methods, but sometimes we can’t remember which class the damn static method is in…

It doesn’t matter, with the extension method, no longer need to worry about this problem, see:

// Add an extension method for String
fun String.helloWorker(a){
	println("Working people, working soul, working people are people!")}"Jack".helloWorker()
"Mark".helloWorker()
//Jack is building bricks and Mark is developing Android. They both have bright futures
Copy the code

Extending methods can add new methods to a class in an almost section-oriented way, without the need for inheritance. Even final modified classes can be extended because they are a distraction for compilation tools (if you are interested, explore the principles of extension functions), but this does not prevent us from using them in development.

Extension functions are very versatile, and extension methods work for both the extended class and its subclasses. It has a wide range of application scenarios. In addition to providing additional methods for some classes (providing a unified anti-connection point for View, providing dp2PX conversion for Int, etc.), it can also expand classes with huge business functions, sort out the complex business logic into the extended classes, and improve the readability of the code.

I have to say, ever since I started stretching, I’ve been eating better.

5. Inline functions

Kotlin provides a series of inline functions: let,with,run,apply, and also to help improve code cleanliness, such as:

user? .username ="Mark"user? .age =18user? .tall =180
// use the let functionuser? .let{ it.username ="Mark"
  it.age = 18
  it.tall = 180} user? .sayHello() user? .sayBye() user? .sayGood()// Use the with functionuser? .with{ sayHello() sayBye() sayGood() }// Most scenarios use run because run is a combination of let and with
Copy the code

The differences between let,with,run,apply and also are as follows:

The function name Objects used in the body of a function The return value Applicable Scenarios
let itRefers to the current object closure Merges multiple null operations
with thisRefers to the current object and can be omitted closure Merge multiple method calls
run thisRefers to the current object and can be omitted closure A combination of let and with
apply thisRefers to the current object and can be omitted this Where run is used, apply is used, mostly to initialize objects
also itRefers to the current object this Let can be used with also, which can be used for function chain calls

In addition to the introverted functions provided by Appeal Kotlin, we can also customize the inline functions. The advantage of an inline function over a normal function is that it copies the function body to the place where the function is called, eliminating the need for stack frames to be pushed in and out of the stack.

String processing

You can reference variables or expressions inside a string, quite a useful feature, many languages have this feature, but Java has not been known to follow.

var str = "My name is ${user.name},I am ${user.age} years old."
// You can omit the braces if you use variables directly
var str2 = "My name is $username"
Copy the code

Kotlin also supports multi-line strings:

var str = "" Hello everybody, my name is${user.name},
	I am ${user.age}"" ".trimIndent()
Copy the code

Multiline strings are useful in some special situations.

Seven, conclusion

Those are some of the features Kotlin uses, but Kotlin has a lot more to offer: streaming operations, lazy loading, the ability to fetch objects in XML without having to findViewById, and so on. And of course the most important: coroutines.

After reading so much, still want to hesitate?

or

If this article can help you, please like, comment and follow us