Kotlin basic grammar study

Simple entry into a door, complex operations in the next section

Kotlin package

  • Unlike Java packages, kotlin packages do not require Java classes to be placed in the same directory as the package name
  • Kotlin class names can also be different from file names
  • Kotlin doesn’t even have to write classes

package base

fun funcMax(a: Int, b: Int): Int {
   return  if(a > b) a else b
}

fun main(args: Array<String>) {
   var a = 10
   var b = 20
   println(funcMax(a, b))
}
Copy the code

Learned Java with the source code to see

public final class FuncDemo01Kt {
   public static final int funcMax(int a, int b) {
      return a > b ? a : b;
   }

   public static final void main(@NotNull String[] args) {
      int a = 10;
      int b = 20;
      intvar3 = funcMax(a, b); System.out.println(var3); }}Copy the code

You can see it here

The Kotlin compiler makes the file FuncDemo01 + Kt a Java class name, while Max is a static method, called a top-level function in Kotlin

So if you call a Kotlin method in a Java class without a class name, consider using the class name. Static functions (funcdemo01kt. funcMax) are used in this way

Here’s how Java calls kotlin’s methods

package base.java;

import base.FuncDemo01Kt;

public class JavaTestDemo01 {
    public static void main(String[] args) throws Exception {
        int a = 10;
        int b = 30; System.out.println(FuncDemo01Kt.funcMax(a, b)); }}Copy the code

Function declaration and definition

The kotlin function definition is done using the fun keyword:

  • Function body form
fun sum(a: Int, b: Int):Int {
    return a + b
}
Copy the code

Fun keyword + space + function name (parameter name: parameter type,...) Function return value {function body}

  • Expression in the body of a function
fun sum(a: Int, b: Int) = a + b
Copy the code

Fun keyword + space + function name (parameter name: parameter type,...) Expression function body (= a + b)

// Kotlin uses the 'Unit' keyword when the function returns no value. Note the distinction between 'Uint' and 'unsigned int', meaning 'unsigned int'
fun sum(a: Int, b: Int):Unit {
    // String template operation keyword '$'
    println("max = ${if(a > b) a else b}")}Copy the code

Statements are usually wrapped around a block of code. In Kotlin, an if statement is an expression. It has a return value, such as: Val Max = if(a > b) a else b But in Kotlin, assignment is a statement, so it can’t

  • What is the expression function body

If the whole body of a function is an expression, we can call it an expression body

fun max(a: Int, b: Int) = if (a > b) a else b
Copy the code

Where = if(a > b) a else b is the expression function body

In the body of an expression function, we can omit the return keyword, as in the if expression above

  • Variable function parameter
fun printArray(vararg arr: Int) {
    for(v in arr) {
        println(v)
    }
}
Copy the code
  • Lambda and anonymous functions
  1. Anonymous functions

A non-anonymous function looks like this:

fun max(x: Int, y: Int): Int {
   return x + y
}
Copy the code

Derive anonymous functions: If you remove the name of a named function, it is an anonymous function. However, if you remove the name, the anonymous function cannot be used by programmers, so you usually need to define a variable or function type parameter to receive it

// The following code is incorrect, there is no way to use the anonymous function
fun (x: Int, y: Int): Int {
   return x + y
}
Copy the code
// The following f is the function type variable
val f = fun (x: Int, y: Int): Int {
   return x + y
}

// Now we can use the function with the f variable
val sum = f(190.29)
Copy the code

We can also use:

fun running(x: Int, y: Int, funType: (Int.Int) - >Int): Int {
   return funcType(x, y)
}

// Call the method
running(10.299.fun (x, y): Int {
   return x + y
})

// lambda expressions
running(10.299, { x, y -> x + y })
// lambda expressions
running(10.299) { x, y ->
   // Write multiple lines of code in the lambda expression
   val ret = x + y
   println("ret = $ret")
   ret
}
Copy the code

Remember: an anonymous function is an object, an object that comes out of a function type new, and a function type is just a type, like Int Double Float String Byte Long and so on, it’s not an object, it’s not an object, it’s not an object, it’s not an object, that’s really useful

  1. Lambda expressions

In Kotlin, any expression wrapped in {} that uses -> split arguments and function bodies is called a lambda expression, for example: {x, y -> if (x > y) x else y}

// lambda expressions
val x: (Int.Int) - >Int = { x, y -> if (x > y) x else y }
// Anonymous function mode
val y: (Int.Int) - >Int = fun(x: Int, y: Int): Int {
   return if (x > y) x else y
}
Copy the code

(Int, Int) -> Int is a function type, but remember it’s not an object it’s not an object it’s not an object it’s not an object, it’s a type

Var f = (Int, Int) -> Int

Var f: (Int, Int) -> Int; var f: (Int, Int) -> Int

// Kotlin initializes the f type using lambda expressions
fun f: (Int.Int) -> Int = { x, y -> x + y }
Copy the code
fun max(x: Int, y: Int): Int {
    return if(x > y) x else y
}
Copy the code
fun sum2(x: Int, y: Int) = x + y
Copy the code

The above two functions have the same return value and parameter type except the function name and function body, and can be directly assigned to the corresponding parameter

The function down here doesn’t work

fun printXY(x: Int, y: Int) = println("x = $x, y = $y")
Copy the code

Its return value is Unit, that is, there is no return value, and (Int, Int) -> Int does not match

// The return value will no longer be an Int
fun sum1(x: Int, y: Int) = {x: Int, y: Int -> x + y}
Copy the code

Fun sum1(x: Int, y: Int) = {x, y -> x + y}

The type of this parameter cannot be inferred. Please specify clearly.

And then I manually added an Int to x and y, but I wonder why? Lambda expression object = to the function. I don’t really know what the = compiler on this function is doing with it, right?

fun sum1(x: Int, y: Int) = {x: Int, y: Int – > x + y} it actually can also be written, but the return value will no longer be the result of x + y type Int, is (Int, Int) – > Int, this way, only shows that we forgot, lambda expressions is also an object, an anonymous function object. And it’s not clear what theta does on the function?

Fun sum1(x: Int, y: Int) = {x: Int, y: Int -> x + y} Why take that extra step? So, the return type changes, of course you can use it that way, but this is just saying what does theta do on the function?

// Use lambda to solve the problem. Emmm
fun sum1(x: Int, y: Int) = {x: Int, y: Int -> x + y}.invoke(x, y)
Copy the code

Fun sum(x: Int, y: Int) = x + y

But it’s important to note that this x+y form is not a lambda anymore. Remember what I said at the beginning? {argument -> function body} this is a lambda expression

The invoke function?

val f = {x, y -> x + y}
// Invoke is also called.
val ret = f.invoke(x, y)
println(ret)
Copy the code

F above is also of type (Int, Int) -> Int

Fun sum(x: Int, y: fun sum(x: Int, y: fun sum(x: Int, y: fun sum(x: Int, y: fun sum(x: Int, y: fun sum)) Int: (Int, Int) -> Int = {x: Int, y: Int -> x + y} why is his return type (Int, Int) -> Int

val f: (Int.Int) - >Int = {x, y -> x + y}
fun sun3(x: Int, y: Int): (Int.Int) - >Int = f
// What is the difference between the top and bottom?
fun sum4(x: Int, y: Int): Double = 3.14159265
Copy the code

Is it something like:

val f: (Int.Int) - >Int = {x, y -> x + y}

fun sum3(x: Int, y: Int): (Int.Int) - >Int {
    return f
}

val d: Double = 3.141592653

fun sum4(x: Int, y: Int): Double {
    return d
}
Copy the code

Do you understand now?

Fun sum4(x: Int, y: Int): Once the = in Double = 3.14159265 is recognized by the compiler, it puts the 3.14159265 object inside a {} and prefaces the object with a return

Such as:

fun sum5(x: Int, y: Int): Unit = println("x + y = ${x + y}")
Copy the code

If I do it the way I did it

fun sum5(x: Int, y: Int): Unit {
    return println("x + y = ${x + y}")}Copy the code

Nothing wrong with it?? In the same way

fun sum1(x: Int, y: Int): (Int.Int) - >Int {
    return {x: Int, y: Int -> x + y}
}
Copy the code

Reminds me of a teacher who told me to learn a programming language from the perspective of a compiler…

variable

Val /var Variable name: the type of the variable

Val is similar to a final variable in Java, and var is a non-final variable that references an immutable variable

When val v: Int is declared, the variable v needs to be initialized later if it is not initialized

// If it is a declaration, you need to determine the type
val v: Int
v = 10
Copy the code

Var defines a variable whose type, once initialized, remains the same the next time it is assigned

var v = 10
v = "hello" // error, v is already an Int, cannot be changed to a String
Copy the code

String formatting template

fun main(args: Array<String>) {
   var a: Int = 99;
   var b = 11; // The type is derived to Int
   println("a = $a, b = $b, a + b = ${a + b}")}Copy the code

The above code is how the Kotlin string template is used

  1. The $variablePrint the value of the variable directly
  2. ${expression}Expressions can be written inside curly braces

When decompiled into Java code, the string manipulation template above becomes

public final class StringDemo01Kt {
   public static final void main(@NotNull String[] args) {
      Intrinsics.checkNotNullParameter(args, "args");
      int a = 99;
      int b = 11;
      String var3 = "a = " + a + ", b = " + b + ", a + b = "+ (a + b); System.out.println(var3); }}Copy the code

Watch window: String var3 = “a =” + a + “, b = “+ b +”, a + b = “+ (a + b);

Classes and properties

  • class

In Java classes are written like this:

public class Person {
    private String name;
    private int age;
    
    public final String getName(a) {
        return this.name;
    }
    
    public final void setName(String name) {
        this.name = name;
    }
    
    public final int getAge(a) {
        return this.age;
    }
    
    public final void setAge(int age) {
        this.age = age;
    }
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age; }}Copy the code

Using IDEA Java to Kotlin code converter converted into Kotlin source code after:

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

It looks much more comfortable

When Java is converted to Kotlin, public is hidden. In Kotlin, the class is public by default, while in Java, it is default (public Default protected private).

Class Person(var name: String, var age: String) class Person(var name: String, var age: String) Int) and the function argument doesn’t need val/var fun sum(a: Int, b: Int) probably because it doesn’t use get/set. Vararg

(vararg arr: String)

  • attribute
  1. The difference between attributes and fields

① In Java: private String name; Get /set = get/set = get/set = get/set = get/set SetProperty (XXX) {this.setProperty(XXX) {this.setProperty(XXX) {this.setProperty(XXX) {this.setProperty(XXX)}} This.property calls this.getProperty() in Java.

(2) in kotlin val/var statement variables, if the val, define a variable will be marked as read-only property, only generates the get method, generating set method, if use var to define variables and generate a set/get methods

When the kotlin attribute var isDelete is encountered, kotlin generates the isDelete and setDeelte methods, with is replaced by set

  • Custom property accessors
class Rectangle(val hight: Int.val width: Int) {
   val isSquare: Boolean
// get() {
// return hight == width
//} // normal function body form
// get() {hight == width} // lamdba form
   get() = hight == width // The expression function body
}
Copy the code
  • In the kotlinimportThe keyword

In Kotlin, you can import classes and top-level functions (called static functions in Java).

Write an extension function in Kotlin (the one that passes this as an argument)

fun String.lasts(a): Char = this[this.length - 1]
Copy the code

If you use the extension function in kotlin, val ch = “kotlin”.lasts()

In Java, it is written like this:

// The core code here passes the call lasts object as an argument, which is done by the Kotlin virtual machine
public static final Char lasts(String /* This is the object on which this method is called, as in the previous example "kotlin" */ this) {
    // "kotlin".charat ("kotlin".length() -1) looks like this
    return this.charAt(this.length() - 1);
}
Copy the code

Come up with some of the following points, and then you can come back to it

If we call the lasts top-level function in another package, we’ll see it above Kotlin

import base.func.lastChar
Copy the code

The previous base.func is the package name, while lastChar is the method

If you want to call it in Java from another package, it becomes

import base.func.ExtensionFuncKt;

public class ExtensionDemo01 {
    public static void main(String[] args) {
        System.out.println(ExtensionFuncKt.lastChar("zhazha")); }}Copy the code

Enumeration class

enum class Color(val r: Int.val g: Int.val b: Int) {
   RED(255.0.0), ORANGE(255.165.0), YELLOW(255.255.0), GREEN(0.255.0), BLUE(
      0.0.255
   ),
   INDIGO(75.0.130), VIOLET(238.130.238);
   
   fun rgb(a) = (r * 256 + g) * 256 + b
   
   fun getWarmth(a) = when (this) {
      RED, ORANGE, YELLOW -> "warm"
      GREEN -> "neutral"
      BLUE, INDIGO, VIOLET -> "cold"}}Copy the code

Use enumeration classes to learn how to use when expressions

When the expression

(1) Use the form of function expression body

fun getWarmth(a) = when (this) {
   RED, ORANGE, YELLOW -> "warm"
   GREEN -> "neutral"
   BLUE, INDIGO, VIOLET -> "cold"
}
Copy the code

(2) Function body form

fun getWarmth1(a): String {
   when (this) {
      RED, ORANGE, YELLOW -> return "warm"
      GREEN -> return "neutral"
      BLUE, INDIGO, VIOLET -> return "cold"}}Copy the code

Intelligent type conversion and IS expression type conversion


interface Expr {}class Num(val value: Int): Expr

class Sum(val left: Expr, val right: Expr): Expr

fun eval(e: Expr): Int {
   if (e is Num) {
      return e.value
   }
   else if (e is Sum) {
      return eval(e.left) + eval(e.right)
   }
   throw IllegalArgumentException("Unknown expression")}fun main(a) {
   println(eval(Sum(Num(1), Sum(Num(2), Num(3)))))}Copy the code

If (e is Num) if the judgment returns true, then the variable e is intelligently converted to Num

However, there is a precondition for using the IS expression: the variable must be a variable defined by val; otherwise, there is no intelligent conversion, and only the conversion shown by the AS expression can be used

println((sum.left as Num).value)

val n = e as Num
Copy the code

We can also use when instead of if expressions

Intervals, sequences and loops

  1. interval

There’s no regular for loop in Kotlin for(int I = 0; i < length; I++), so introducing intervals is a better substitute for this operation

1.. 10 interval expression, representing the number between [1, 10], including 1 and 10

fun main(a) {
   val interval: IntRange = 1.10.
   for (v in interval) {
      print("$v ")
   }
   
   println()
   for (v in interval.last downTo interval.first step 1) {
      print("$v ")
   }
   println()
   
   / / [1, 10)
   for (v in interval.first until interval.last) {
      print("$v ")}}Copy the code
1 2 3 4 5 6 7 8 9 10 
10 9 8 7 6 5 4 3 2 1 
1 2 3 4 5 6 7 8 9 
Copy the code
  1. Iterative map
fun main(a) {
   val map = mutableMapOf(
      1 to "zhazha".2 to "haha".3 to "haha",
      Pair(4."xixi"),
      Pair<Int, String>(5."heihei")
   )
   
   map.forEach(fun(m: Map.Entry<Int, String>): Unit {
      println("key = ${m.key}, value = ${m.value}")})for ((key, value) in map) {
      println("key = $key, value = $value")}// java forEach??? Call the BiConsumer interface in the Java Map
   map.forEach { key, value ->
      println("key = $key, value = $value")}// Kotlin forEach??? Call kotlin's (key, value) -> {} to traverse the Map method
   map.forEach { (key, value) ->
      println("key = $key, value = $value")}}Copy the code
fun Set<String>.inSet(str: String) = str in this

val set = setOf<String>("1"."2"."3"."4"."a"."b"."c")

println(set.inSet("a"))

// (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
fun isLetter(ch: Char) = ch in 'a'.'z' || ch in 'A'.'Z'

// ch >= '0' && ch <= '9'
fun inNumber(ch: Char) = ch in '0'.'9'
Copy the code

Kotlin abnormal

In Kotlin, exceptions may or may not be handled. They are not on the function declaration, throw new Exception(” XXXX “) is not required.

fun main(a) {
   val bufferedReader = BufferedReader(InputStreamReader(System.`in`))
   val number = readNumber(bufferedReader)
   println(number)
}

fun readNumber(reader: BufferedReader): Int? = try {
   val line = reader.readLine()
   Integer.parseInt(line)
} catch (e: NumberFormatException) {
   throw e
} finally {
   reader.close()
}
Copy the code