1, Basic data type
Several are introduced.
- value type
- Character type
- Boolean
1.1 value type
The basic numeric types of Kotlin include Byte, Short, Int, Float, Long and Double
data type | Bit length |
---|---|
Byte | 8 |
Short | 16 |
Int | 32 |
Float | 32 |
Long | 64 |
Double | 64 |
It is described in the following situations:
- Use of value type;
- Conversion of numeric type to binary, octal and hexadecimal;
- Numerical comparison;
- Value type conversion;
- Numeric type bit operation;
1.1.1 value type usage
Basic numeric types (Byte, Short, Int, Float, Long, Double) are used.
Numerical method: // Int: numeric type variable definition // Var < identifier >: < type > = < initialization value > val aa: Int = 123 val aa = 123 // Float: use f or F suffix val aa = 123.5f val bb = 123.5F // Long: ends with a capital L val aa = 1234_5678_9012_3456L // Double default val aa = 123.5
1.1.2 binary, octal and hexadecimal
Basic value type, binary, octal and hexadecimal support.
// Decimal: 123 val aa = 123 // Binary: beginning with 0b val aa = 0b00001011 // Octal: temporarily not supported // Hex: beginning with 0x val aa = 0x0F
1.1.3 numerical comparison
There are no basic data types in Kotlin, only encapsulated digital types.
For each variable we define, Kotlin actually encapsulates an object for you, which can ensure that there will be no null pointer. Therefore, when comparing two numbers, there is a difference between comparing the data size and whether the two objects are the same.
In Kotlin:
- Three equal signs = = = indicate the address of the comparison object;
- Two = = means comparing the size of two values.
// Address space comparison (same object) val a: Int = 10000 println(a === a) // true // Address space comparison (different objects) val boxedA: Int? = a val anotherBoxedA: Int? = a println(boxedA === anotherBoxedA) // false object address is different // Size comparison println(boxedA == anotherBoxedA) // true, equal values
1.1.4 type conversion
Due to different representations, the smaller type is not a subtype of the larger type.
Therefore, smaller types cannot be implicitly converted to larger types. Therefore, if Byte is converted to Int, display conversion is required.
val b: Byte = 1 // Display conversion val i: Int = b.toInt()
Each data type has the following methods, which can be converted to other types:
toByte(): Byte toShort(): Short toInt(): Int toLong(): Long toFloat(): Float toDouble(): Double toChar(): Char
1.1.5 bit operation
// Left shift shl(bits) // Right shift shr(bits) // Unsigned right shift ushr(bits) // And and(bits) // or or(bits) // XOR xor(bits) // reverse inv()
1.2 character type
Char must be enclosed in single quotation marks'. For example, ordinary characters' 0 'and' a '.
// Address space comparison (same object) val a: Char = '9' // Display conversion val i: Int = a.toInt()
1.3 string
String variable declaration:
// Single line string val str = "123" // Multiline string val text = """ Multiline string Multiline string """
String usage:
// Take the characters in the string val str = "123" println(str[2]) // Take the characters in the string for (c in str) { println(c) } // Display character conversion val i: Int = str.toInt{) // Go space val text = """ Multiline string Multiline string """.trimMargin()
String template:
// $represents a variable name or value // $varName represents the value of the variable // ${varName.fun()} represents the method return value of the variable fun main(args: Array<String>) { var a = 1 // Simple name in template: val s1 = "a is $a" // Any expression in the template: val s2 = "${s1.replace("is", "was")}, now is $a" print(s2) }
Boolean 1.3
Boolean is represented by Boolean type, which has two values: true and false.
val b: Boolean = true
2, Variable
- Variable definition
- Variable NULL check
- Variable type detection is
- Variable interval representation
- Variable length parameter vararg
2.1 variable definition
- var variable;
- val read-only variable, which is equivalent to the final variable in java. val variable must be initialized when it is created.
var <Variable identifier> : <Variable type> = <Variable initialization value> // Variable initialization: var a: Int = 1 // Read only variable initialization: val b: Int = 2
2.2 variable NULL check
- Type followed by? Indicates that it can be empty
var aa: String? = "23" - Add after identifier!! Indicates that if it is null, an exception is thrown normally;
val aa = age!!.toInt() - Add after Identifier? Indicates that if it is empty, it returns null
val aa = age?.toInt() - ?: Use: Return - 1 if age is null
val ages2 = age?.toInt() ?: -1
2.3 variable type detection
// Type detection if (obj is String) { // After type judgment, obj will be automatically converted to String type by the system return obj.length }
2.4 variable interval
- Use... To represent rangeTo (from small to large)
for (i in 1..4) print(i) / / output "1234" - Use downTo (from large to small)
for (i in 4 downTo 1 step 2) print(i) / / output "42" - Use step to specify the step size
for (i in 1..4 step 2) print(i) / / output "13" - Use until to exclude end elements
// i in [1, 10) excludes 10 for (i in 1 until 10) { println(i) }
2.5 variable length parameters
Variable side length parameter vararg
fun vars(vararg v:Int){ for(vt in v){ print(vt) } } // test fun main(args: Array<String>) { vars(1,2,3,4,5) // Output 12345 }
3, Method
- Method definition
- lambda anonymous method
3.1 method definition
Keyword used in method definition: fun,
Parameter format: parameter type
// Method definition with return value fun sum(a: Int, b: Int): Int { // Int parameter, return value int return a + b } // No return value method definition fun printSum(a: Int, b: Int) { print(a + b) }
3.2 lambda anonymous method
// test fun main(args: Array<String>) { val sumLambda: (Int, Int) -> Int = {x,y -> x+y} println(sumLambda(1,2)) // Output 3 }
4, Condition control
- if expression
- when expression
4.1 if expression
An if statement contains a Boolean expression and one or more statements.
// Use if else var max: Int if (a > b) { max = a } else { max = b } // Use if expressions var max = a if (a < b) max = b // Use as an expression: assign the result of the expression to a variable val max = if (a > b) a else b // Use as an expression: assign the result of the expression to a variable val max = if (a > b) { a } else { b }
4.2 when expression
when compares its parameters with all branch conditions in order until a branch satisfies the condition.
when is similar to the switch operator in other languages.
The when expression else is the same as the default of switch. If other branches do not meet the conditions, the else branch will be evaluated.
// when (x) { 1 -> print("x == 1") 2 -> print("x == 2") else -> { // Pay attention to this block print("x Not 1, not 2") } } // when (x) { 0, 1 -> print("x == 0 or x == 1") else -> print("otherwise") }
when expression, use in to detect whether a value is in or not in an interval or set:
// when (x) { in 1..10 -> print("x is in the range") in validNumbers -> print("x is valid") !in 10..20 -> print("x is outside the range") else -> print("none of the above") }
when expression, use is to detect whether a value is or is not a specific type of value:
// when(x) { is String -> x.startsWith("prefix") else -> false }
5, Cycle control
- for loop
- While and do while
- return, break and continue
5.1 for loop
The for loop can traverse any object that provides an iterator.
// for (item in collection) print(item) // The loop body can also be a statement val items = listOf("apple", "banana", "kiwi") for (item in items) println(item) // The loop body can also be a block of code val items = listOf("apple", "banana", "kiwi") for (item in items) { println(item) } // Traversing an array or a list by index for (i in array.indices) { print(array[i]) } // Using the withIndex library method for ((index, value) in array.withIndex()) { println("the element at $index is $value") }
5.2 while and do while
The functions of while and do while are similar; The difference is that do while is executed at least once.
fun main(args: Array<String>) { // while loop var x = 5 while (x > 0) { println( x--) } // do... while loop var y = -1 do { println(y--) } while(y>0) } // results of enforcement // while loop 5 4 3 2 1 // do... while loop -1
5.3 return, break and continue
- return returns from the method that most directly surrounds it or the anonymous method;
- break terminates the loop that most directly surrounds it;
- continue continues the next cycle that most directly surrounds it;
Examples of usage are as follows:
fun main(args: Array<String>) { for (i in 1..10) { if (i==3) continue // When i is 3, skip the current cycle and continue the next cycle println(i) if (i>5) break // Jump out of loop when i is 6 } }
Tags in Kotlin
In Kotlin, any expression can be marked with a label.
The format of label is identifier followed by @ symbol. For example, abc @ and fooBar @ are valid labels.
// Limit break with label loop@ for (i in 1..100) { for (j in 1..100) { if (......) break@loop } }
6, Class
- Class definition
- abstract class
- Nested class
- Inner class
- Anonymous Inner Class
6.1 class definition
- Class keyword
Class is declared with the keyword class, followed by the class name:
class Person{} - Main construction method
A class can have a primary constructor and multiple secondary constructors.
The main constructor is part of the class header, after the class name. The main constructor cannot contain any code. The initialization code can be placed in the initialization code segment init. - Secondary construction method
If the class has a primary constructor, each secondary constructor must directly or indirectly proxy the primary constructor through another secondary constructor; Use this keyword to proxy another constructor in the same class; - Class attribute declaration
Non empty attributes in the class must be initialized at the time of definition, but they can also be delayed through the lateinit keyword.
In addition, Kotlin provides a back-end variable field mechanism, but the field keyword can only be applied to the accessor of the attribute.
Examples of Kotlin class construction codes are as follows:
// Class keyword: the class uses the keyword class declaration, followed by the class name; // Construction method: class with construction method (constructor keyword can be omitted); class Person constructor (name: String){ // Class attribute: non empty attribute must be initialized at the time of definition; // Class attribute: Kotlin provides a back-end variable field mechanism, but the field keyword can only be applied to the accessor of the attribute; var mName: String = "xia" get() = field.toUpperCase() // Convert variable to uppercase after assignment var mAge: Int = 16 set(value) { if (value < 20) { // If the value passed in is less than 20, this value is returned field = value } else { field = 18 // Otherwise, return to 18 } } // Construction method: the main constructor cannot contain any code, and the initialization code can be placed in the init code segment; init { this.mName = name println("init name $mName") println("init age $mAge") } // Secondary construction method: if the class has a primary construction method, each secondary construction method must directly or indirectly proxy the primary construction method through another secondary construction method; // Secondary constructor: use this keyword on behalf of another constructor in the same class; constructor (name: String, age:Int) : this(name) { // Secondary construction method this.mName = name this.mAge = age println("constructor init name $mName") println("constructor init age $mAge") } } // main program entry fun main(args: Array<String>) { // create object var person: Person = Person("xiaxl") // full name person.mName = "xiaxueliang" println("changeName:${person.mName}") // Age person.mAge = 21 println("changeAge:${person.mAge}") }
6.2 abstract classes
Abstract class itself and some members in the class can be declared as abstract type.
// Abstract class itself and some members in the class can be declared as abstract type abstract class Person { abstract fun changeName() }
6.3 nested classes
You can nest classes in other classes.
// Nested classes: you can nest classes in other classes // External class class Outer { private val outerProperty: Int = 1 // Nested class class Person { fun changeAge() = 18 } } fun main(args: Array<String>) { // Nested classes: calling external classes Nested classes Nested class methods / properties val age = Outer.Person().changeAge() println(age) // Output 18 }
6.4 internal class
The inner class is represented by the inner keyword.
The inner class will have a reference to the object of the outer class, so you can access the member properties and methods of the outer class. Can use this@label Tag to access this from an external scope.
// Inner class: the inner class is represented by the inner keyword. // Internal class: the internal class will have a reference to the object of the external class, so you can access the member properties and methods of the external class. class Outer { private val iProperty: Int = 18 var sProperty = "outerName" // Inner class inner class Person { // Accessing external class members fun test01() = iProperty // Get the external class object and access the external class members fun test02() { // Internal classes: Using` this@label `Tag, access from external scope ` this` var outerObj = this@Outer // Accessing external class members println("inner sProperty: " + outerObj.sProperty) } } } fun main(args: Array<String>) { val iProperty = Outer().Person().test01() println("main Person test01: " + iProperty) // val sProperty = Outer().Person().test02() println("main Person test02: " + sProperty) }
6.5 anonymous inner class
// Define interface interface PersionInterFace { fun changeName() } // Define class class Persion { var v = "Member properties" // Definition method fun setInterFace(testObj: PersionInterFace) { testObj.changeName() } } // Program entry fun main(args: Array<String>) { // Gets the object of the class var persion = Persion() // An object expression is used to create an interface object, that is, an instance of an anonymous inner class. persion.setInterFace(object : PersionInterFace { override fun changeName() { println("Implementation of anonymous inner classes changeName method") } }) }
7, Inherit
All classes in Kotlin inherit the Any class, which is a superclass of all classes.
In addition, Any class provides three methods by default: equals(), hashCode(), toString().
- Construction method
- override method
- Overridden properties
7.1 construction method
- If the subclass has a main constructor:
The base class must be initialized in the subclass main constructor.
// If the subclass has a main constructor: the base class must be initialized in the main constructor of the subclass. // Base class // If a class is to be inherited, it can be decorated with the open keyword // Any class is a superclass of all classes open class Person(var name:String, var age:Int){ } // Subclass Student class Student(name:String, age:Int, ,number:String) : Person(name, age) { } // test fun main(args: Array<String>) { var s = Student("xia", 18, "n987456123") println("full name: ${name}") println("Age: ${age}") println("Student number: ${number}") }
- If the subclass does not have a primary constructor:
You must initialize the base class with the super keyword in each secondary constructor of the subclass.
// If the subclass does not have a primary constructor: the base class must be initialized with the super keyword in each secondary constructor of the subclass. // Base class open class Person(name:String){ // Construction method of base class constructor(name:String,age:Int):this(name){ println("--- Construction method of base class ---") println("full name: ${name}") println("Age: ${age}") } } // Subclass Student class Student:Person{ // Subclass sub construction method constructor(name:String,age:Int,number:String):super(name,age){ println("--- Subclass secondary construction method ---") println("full name: ${name}") println("Age: ${age}") println("Student number: ${number}") } } fun main(args: Array<String>) { var s = Student("xia", 18, "number987456123") }
7.2 rewriting method
In the base class, when declaring a function method, this method defaults to final and cannot be overridden by subclasses.
If subclasses are allowed to override this method, you need to manually add an open modifier, and subclass override methods need to use the override keyword.
// Base class // Method override: in the base class, when using fun to declare a function method, this function method defaults to final and cannot be overridden by subclasses. // Method Rewriting: if subclasses are allowed to rewrite this method, you need to manually add an open modifier, and subclass rewriting methods need to use the override keyword. open class Person{ // Allow subclass overrides open fun study(){ println("Learning makes me happy") } } // Subclass class Student : Person() { // rewrite override fun study(){ println("I am a student.") } } // Program entry fun main(args: Array<String>) { val s = Student() s.study(); }
7.3 override attributes
Use the override keyword, or you can use the override keyword in the main constructor as part of the property declaration.
interface Persion { val age: Int } // Override attribute: use override keyword class Student1 : Persion { override var age: Int = 9 } // Override attribute: use the override keyword in the main constructor as part of the attribute declaration class Student2(override val age: Int) : Persion{ } // Program entry fun main(args: Array<String>) { var s1 = Student1() println("Student1: "+s1.age); var s2 = Student2(18) println("Student2: "+s2.age); }
8, Interface
Kotlin uses the interface keyword to define an interface.
- Methods in the interface are allowed to have default implementation;
- Attributes in an interface can only be abstract and cannot be initialized;
- A class can implement one or more interfaces. When implementing multiple interfaces, you may encounter the problem that the same method inherits multiple implementations.
// Interface class A interface AInterface { // Interface: attributes can only be abstract and cannot be initialized var name:String // Interface: method can have default implementation // Unimplemented method fun changeName() // Implemented methods fun changeAge() { println("AInterface changeAge") } } // Interface class B interface BInterface { // Interface: method can have default implementation // Unimplemented method fun changeName() { println("BInterface changeName") } // Implemented methods fun changeAge() { println("BInterface changeAge") } } class C : AInterface { // Overridden properties override var name: String = "xiaxl" // override method override fun changeName() { println("Class C changeName") } } class D : AInterface, BInterface { // Overridden properties override var name: String = "xiaxl" // override method override fun changeName() { // super<AInterface>.changeName() super<BInterface>.changeName() println("Class D changeName") } // override method override fun changeAge() { super<BInterface>.changeAge() println("Class D changeAge") } } fun main(args: Array<String>) { val d = D() println(" ") d.changeName(); println(" ") d.changeAge(); }
9, Enumeration
enum class Color(val rgbValue: Int) { RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF) } fun main(args: Array<String>) { // var color:Color=Color.GREEN // Print enumeration name println(color.name) // Print enumeration order println(color.ordinal) // Print enumerated values println(color.rgbValue) }
10, Data type
First, why use data classes:
The advantage of Kotlin replacing ordinary classes with data classes is that Kotlin will help us generate a lot of code and save a lot of repetitive work.
- To use a data class in Kotlin, you only need to add the data keyword before the class keyword. The compiler will automatically deduce the related functions equals(), toString(), copy(), componentN(), hashCode(), from the main constructor according to the declared attributes;
- In Kotlin, the data class automatically declares the attribute field with the same name as the constructor input parameter, and automatically implements the accessor method set/get of each attribute field;
Declare data class:
// Declare data type data class <Class name> <Primary constructor parameters> <:Inheritance classes and implementation interfaces> { /*Class body*/ }
Examples of data types:
// Create data class data class Person(var name :String, var age :Int){ // In vivo life attribute var job: String = "student" } // Program entry fun main(args: Array<String>) { var p = Person("xiaxl",18) // Call getter of data class println(p.name) println(p.age) println(p.job) // Call the setter of the data class p.name = "xiaxueliang" // Automatically call toString() method println(p) //Call the hashCode() method to output the memory address println(p.hashCode()) // Resolve constructor componentN val (name, age) = p println("name = $name, age=$age") }
11, Generics
// Generic example class Persion<T>(t : T) { var value = t } // Generic example fun <T> doPrintln(t: T) { when (t) { is Int -> println("Integer number: $t") is String -> println("string uppercase : ${t.toUpperCase()}") else -> println(" Not an integer, not a string") } } // Program entry fun main(args: Array<String>) { var pInt = Persion<Int>(18) var pString = Persion<String>("xiaxl") // output doPrintln(pInt.value) doPrintln(pString.value) }
12, Associated object
- Companion Object
- Object declaration
12.1 associated objects
Associated objects exist with the existence of classes.
In kotlin, classes do not have static methods. In most cases, kotlin recommends using package level functions as static methods. Kotlin will treat package level functions as static methods.
// Companion Object class MyConstant { companion object { var num: Int = 100 fun doPrint() { println("method test") } } } // Program entry fun main(args: Array<String>) { // variable var num = MyConstant.num println("num: $num") // method MyConstant.doPrint() }
12.2 object declaration
Kotlin can obtain a singleton through object declaration. Kotlin uses the object keyword to declare an object.
// Object declaration object Singleton{ // attribute val name = "xia" // method fun doPrint(age: Int){ println("$name ---- $age") } } // Program entry fun main(args: Array<String>) { // Single case Singleton.doPrint(18) }