This time, I will talk about Kotlin’s variables and constants. I will mainly introduce the following:

  • 1. Basic definition of variables
  • Var and val
  • 3. Intelligent type inference
  • 4. Custom property accessors
  • 5. Is var mutable and val immutable

Kotlin vs. the use of variables and constants in Java

  • Define a variable and a constant in Java
public String name = "Mikyou";// Define variables
public final int age = 18;//final defines constants
Copy the code
  • 2. Define a variable and a constant in Kotlin
var name: String = "Mikyou"
val age: Int = 18
Copy the code

or

var name = "Mikyou"
val age = 18
Copy the code

Conclusion: From the above comparison, it can be concluded that:

  • 1. Kotlin defines a variable and constant more succinct and flexible than Java
  • 2. Kotlin has a type inference mechanism. When a variable or constant is initialized, it can omit the type declaration, and it will use the type of the variable according to the type of the initialized value.
  • 3. Kotlin must declare variables and constants using the var keyword, val keyword, name, and type (if there is an initializer type can be omitted)
  • 4. Kotlin compares Java’s default access modifier to public, whereas In Java it is default
  • 5. Java generally starts with a type followed by a name, and the type cannot be omitted; Such operations are not possible in Kotlin. Because in Kotlin types can be omitted, that is, they are relatively weak, Kotlin puts the type last, generally omitting the type declaration that follows if it contains an initialization value.

Kotlin’s use of variables and constants

var name: String = "Mikyou"
var address: String?// If the variable is not initialized, the declared type needs to be displayed and whether the type is nullable
address = "NanJing"
val age: Int = 18
Copy the code

or

var name = "Mikyou"
val age = 18
Copy the code
  • Variable and constant declarations must begin with the keywords “var” and “val”.
  • 2, the structure of the variables and constants: (var or val) name: (comma) segmentation variable type = initialization values.
  • 3. Smart cast (the compiler prompts smart cast). If a variable or constant contains an initial value that can be omitted, the compiler will parse the initialized value as the type of the variable and constant by default.
  • 4. If the variable is not initialized, you need to display the declared type and specify whether the type is nullable.

Kotlin’s custom property accessor

Properties are a first-class feature in Kotlin, which is used to replacing fields and setters and getters in Java with a property. The set and get accessors in Kotlin are the Java equivalent of setters and getters. One of Kotlin’s new features is the ability to define accessors for properties in a class including setter, getter accessors. This feature is ideal for a new attribute that requires multiple attribute logic calculations. Then the procedure operation of logical computation does not need to open a method to implement like Java. Logical operations can be performed directly in the property accessor.

  • 1. Customize the get accessor

Implementation in Java:

public class Rectangle {

    private float width;
    private float height;

    public Rectangle(float width, float height) {
        this.width = width;
        this.height = height;
    }

    public boolean isSquare(a) {// Implement a method in Java to perform related logical calculations
        returnwidth == height; }}Copy the code

Implementation in Kotlin:

class Rectangle(width: Float, height: Float) {
    val isSquare: Boolean// In Kotlin, only one property is needed, redefining isSquare's getter property accessor, which can write specific logic code.
        get() {
            return width == height
        }
}
Copy the code
  • 2. Customize set accessors

Implement setter methods in a custom View in Android in Java.

public class RoundImageView extends ImageView {...public void setBorderColor(int color) { mColor = color; invalidate(); }... }Copy the code

Kotlin in Android implementation of a custom View in the set attribute accessor.

class RoundImageView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defAttrStyle: Int = 0)
    : ImageView(context, attributeSet, defAttrStyle) {

    var mBorderColor: Int
        set(value) {// Customize the accessor for the set attribute
            field = value
            invalidate()
        }
}
Copy the code

Var and val in Kotlin

  • 1. Var (from variable) variable references. And the value of the variable modified by it can be changed, with readable and writable permissions, equivalent to non-final variables in Java.
  • Val (from value) is immutable reference. And the value of the variable it modifiers is normally initialized once and cannot be initialized again otherwise a compilation exception will be thrown, which is equivalent to a final modifier in Java.
  • 3. Declare all Kotlin variables with the val keyword as much as possible during Kotlin development, and only use var in some special cases. We all know that functions are first class citizens in Kotlin, and add a lot of functional programming content, while using immutable reference variables makes it closer to functional programming style.
  • Note that the reference to val itself is immutable, but the object it refers to can be mutable (see the discussion of immutable and readable val in Kotlin for a discussion and proof of this).
  • 5. The var keyword allows you to change its value, but its type is immutable.

5. Discussion on immutable and readable val in Kotlin

Because Kotlin is a new language, we tend to memorize theorems in the process of learning without really digging into why. Take today’s topic for example. I believe that many people (including myself at first) believe that var variables are mutable and val variables are immutable. Then Kotlin’s custom property accessor becomes problematic. Then I went to read some foreign blogs. Although it was described, I was more confused after reading that the value of the variable modified by val can be changed and readable, and the underlying reference is also changed. The former sentence is indeed understandable, but the latter one is still reserved. So I started writing demo authentication. “But can we say that val guarantees that reference to the object is immutable? No…” Source address of foreign blog

  • 1. Assumption that Val is immutable and readable

Assumption 1: In Kotlin, val modifiers cannot be said to be immutable, only that val modifiers have permissions that are readable.

Assumption 2: The reference to a variable modified by val in Koltin is immutable, but the object to which it refers is mutable.

  • 2, Val immutable and readable arguments

Argument hypothesis 1: During Kotlin’s development, variables decorated with val cannot be assigned again, otherwise a compile-time exception will be thrown. But just because it can’t be assigned again doesn’t mean it’s immutable. Unlike Java, Kotlin has a custom property accessor feature. This property seems to contradict the fact that val is immutable. This problem does not exist in Java, where there is no concept of a custom accessor if you use a final modified variable.

fun main(args: Array<String>) {
    val name = "Hello Kotlin"
    name = "Hello Java"
}
Copy the code

print error:

Error:(8, 5) Kotlin: Val cannot be reassigned
Copy the code

Define the get property accessor example

class RandomNum {
    val num: Int
        get() = Random().nextInt()
}

fun main(args: Array<String>) {
    println("the num is ${RandomNum().num}")}Copy the code

print result:

the num is -1411951962
the num is -1719429461
Copy the code

Conclusion: The above example shows that hypothesis 1 is true. The variable modified by val in Kotlin cannot be said to be immutable, but can only be read.

Argument hypothesis 2: From argument 1, we know that Kotlin’s val modifier is mutable, but is its underlying reference mutable? A foreign blog said that citation is mutable, is it true? Let me give you an example.

The User class:

package com.mikyou.kotlin.valtest
open class User() {
    var name: String? = "test"
    var age: Int = 18
    var career: String? = "Student"
}
Copy the code

Student class:

class Student() : User()
Copy the code

The Teacher class:

class Teacher() : User()
Copy the code

The Customer interface:

interface Customer {
    val user: User// Note that this is a reference to the User instance decorated with val
}
Copy the code

VipCustomer implementation class:

class VipCustomer : Customer {
    override val user: User
        get() {
// return Student().apply {
// name = "mikyou"
// age = 18
// career = "HighStudent"
/ /}
            return Teacher().apply {
                // The underlying reference will also change. After all, Student and Teacher are different objects. But is this the case?
                name = "youkmi"
                age = 28
                career = "HighTeacher"}}}Copy the code

Testing:

fun main(args: Array<String>) = VipCustomer().user.run {
    println("my name is $name, I'm $age years old, my career is $career, my unique hash code is ${hashCode()} ")}Copy the code

print result:

my name is mikyou, I'M 18 years old, my career is HighStudent, my unique hash code is 666988784 // Switch to Teacher my name is youkmi, I'm 28 years old, my career is HighTeacher, my unique hash code is 666988784
Copy the code

Conclusion: The above example shows that hypothesis 2 is true, as two different objects hashCode, the reference address of user is unchanged, but the change is that the reference to the object can be changed.

This concludes Kotlin’s introduction to basic syntax, and the next article will continue to delve into Kotlin

Welcome to the Kotlin Developer Association, where the latest Kotlin technical articles are published, and a weekly Kotlin foreign technical article is translated from time to time. If you like Kotlin, welcome to join us ~~~