Kotlin Basic Syntax
Kotlin files use the .kt extension.
## Package Declaration
The beginning of a code file is generally the package declaration:
```kotlin
package com.tutorial.main
import java.util.*
fun test() {}
class Tutorial {}
Kotlin source files do not require matching directories and packages. Source files can be placed in any file directory.
In the example above, the full name of `test()` is `com.tutorial.main.test`, and the full name of `Tutorial` is `com.tutorial.main.Tutorial`.
If no package is specified, it defaults to the `default` package.
### Default Imports
Several packages are imported by default into every Kotlin file:
* kotlin.*
* kotlin.annotation.*
* kotlin.collections.*
* kotlin.comparisons.*
* kotlin.io.*
* kotlin.ranges.*
* kotlin.sequences.*
* kotlin.text.*
* * *
## Function Definition
Function definitions use the `fun` keyword. The parameter format is: `parameter : Type`
```kotlin
fun sum(a: Int, b: Int): Int { // Int parameters, return value Int
return a + b
}
An expression can be used as the function body, with the return type inferred automatically:
```kotlin
fun sum(a: Int, b: Int) = a + b
public fun sum(a: Int, b: Int): Int = a + b // For public methods, the return type must be explicitly stated
A function with no return value (similar to Java's void):
```kotlin
fun printSum(a: Int, b: Int): Unit {
print(a + b)
}
// If the return type is Unit, it can be omitted (this also applies to public methods):
public fun printSum(a: Int, b: Int) {
print(a + b)
}
### Variable-Length Argument Functions
A function's variable-length arguments can be marked with the `vararg` keyword:
```kotlin
fun vars(vararg v:Int){
for(vt in v){
print(vt)
}
}
// Test
fun main(args: Array) {
vars(1,2,3,4,5) // Outputs 12345
}
### Lambda (Anonymous Function)
Example of using a lambda expression:
```kotlin
// Test
fun main(args: Array) {
val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
println(sumLambda(1,2)) // Outputs 3
}
* * *
## Defining Constants and Variables
Mutable variable definition: `var` keyword
```kotlin
var : =
Immutable variable definition: `val` keyword, a variable that can only be assigned once (similar to a variable modified by `final` in Java)
```kotlin
val : =
Constants and variables can both have no initialization value, but they must be initialized before being referenced.
The compiler supports automatic type inference, meaning you don't need to specify the type when declaring it; the compiler will determine it.
```kotlin
val a: Int = 1
val b = 1 // System automatically infers the variable type as Int
val c: Int // If not initialized at declaration, the variable type must be provided
c = 1 // Explicit assignment
var x = 5 // System automatically infers the variable type as Int
x += 1 // Variable can be modified
* * *
## Comments
Kotlin supports single-line and multi-line comments, as shown in the following examples:
```kotlin
// This is a single-line comment
/* This is a multi-line
block comment. */
Unlike Java, block comments in Kotlin allow nesting.
* * *
## String Templates
`$` denotes a variable name or variable value.
`$varName` represents the variable's value.
`${varName.fun()}` represents the return value of a method on the variable:
```kotlin
var a = 1
// Simple name in the template:
val s1 = "a is $a"
a = 2
// Arbitrary expression in the template:
val s2 = "${s1.replace("is", "was")}, but now is $a"
* * *
## NULL Safety Mechanism
Kotlin's null safety design requires null-checking for parameters declared as nullable. There are two ways to handle this: adding `!!` after the field to throw a null exception like Java, or adding `?` after the field to return **null** without handling, or using `?:` for null-checking.
```kotlin
// Adding ? after the type indicates it can be null
var age: String? = "23"
// Throws a NullPointerException
val ages = age!!.toInt()
// Returns null without handling
val ages1 = age?.toInt()
// Returns -1 if age is null
val ages2 = age?.toInt() ?: -1
When a reference might be null, the corresponding type declaration must be explicitly marked as nullable.
When the string content in `str` is not an integer, it returns null:
```kotlin
fun parseInt(str: String): Int? {
// ...
}
The following example demonstrates how to use a function that can return a null value:
```kotlin
fun parseInt(str: String): Int? {
return str.toIntOrNull()
}
fun printProduct(arg1: String, arg2: String) {
val x = parseInt(arg1)
val y = parseInt(arg2)
// Using `x * y` directly would cause an error because they might be null
if (x != null && y != null) {
// After the null value check, the types of x and y are automatically converted to non-null variables
println(x * y)
} else {
println("'$arg1' or '$arg2' is not a number")
}
}
fun main() {
printProduct("6", "7")
printProduct("a", "7")
printProduct("a", "b")
}
Or:
```kotlin
fun parseInt(str: String): Int? {
return str.toIntOrNull()
}
fun printProduct(arg1: String, arg2: String) {
val x = parseInt(arg1)
val y = parseInt(arg2)
// ...
if (x == null) {
println("Wrong number format in arg1: '$arg1'")
return
}
if (y == null) {
println("Wrong number format in arg2: '$arg2'")
return
}
// After the null value check, the types of x and y are automatically converted to non-null variables
println(x * y)
}
fun main() {
printProduct("6", "7")
printProduct("a", "7")
printProduct("99", "b")
}
* * *
## Type Checking and Automatic Type Casting
We can use the `is` operator to check if an object is an instance of a specified type (similar to the `instanceof` keyword in Java).
```kotlin
if (obj is Type) {
// If obj is of Type, you can directly use the properties and methods of the Type
} else {
// Handle other type cases
}
When the `is` check passes, Kotlin automatically treats `obj` as the specified type, so there's no need for explicit type casting within the `if` statement's branch. This is called **smart casting**.
## Example
```kotlin
fun main() {
val obj: Any = "Hello, Kotlin"
if (obj is String) {
println("String length: ${obj.length}") // Here `obj` has been smart-cast to `String`
} else {
println("Not a string type")
}
}
In this example, if `obj` is of type `String`, the `is` operator returns `true`, and Kotlin recognizes `obj` as a `String`, allowing direct access to `String` type properties and methods.
More applications:
```kotlin
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// After the type check, obj is automatically converted to String type by the system
return obj.length
}
// Here is another way, different from Java's instanceof, using !is
// if (obj !is String){
// // XXX
// }
// Here obj is still an Any type reference
return null
}
Or
```kotlin
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null
// In this branch, the type of `obj` is automatically converted to `String`
return obj.length
}
Even
```kotlin
fun getStringLength(obj: Any): Int? {
// On the right side of the `&&` operator, the type of `obj` is automatically converted to `String`
if (obj is String && obj.length > 0)
return obj.length
return null
}
* * *
## Ranges
Range expressions are formed with the `rangeTo` operator function (`..`) supplemented by `in` and `!in`.
Ranges are defined for any comparable type, but for integer primitive types, there is an optimized implementation. Here are some examples of using ranges:
```kotlin
for (i in 1..4) print(i) // Outputs "1234"
for (i in 4..1) print(i) // Outputs nothing
if (i in 1..10) { // Equivalent to 1 <= i && i <= 10
println(i)
}
// Using step to specify the step size
for (i in 1..4 step 2) print(i) // Outputs "13"
for (i in 4 downTo 1 step 2) print(i) // Outputs "42"
// Using the until function to exclude the end element
for (i in 1 until 10) { // i in [1, 10) excludes 10
println(i)
}
### Example Test
```kotlin
fun main(args: Array) {
print("Loop output: ")
for (i in 1..4) print(i) // Outputs "1234"
println("n----------------")
print("Set step size: ")
for (i in 1..4 step 2) print(i) // Outputs "13"
println("n----------------")
print("Use downTo: ")
for (i in 4 downTo 1 step 2) print(i) // Outputs "42"
println("n----------------")
print("Use until: ")
// Using the until function to exclude the end element
for (i in 1 until 4) { // i in [1, 4) excludes 4
print(i)
}
println("n----------------")
}
Output:
Loop output: 1234
----------------
Set step size: 13
----------------
Use downTo: 42
----------------
Use until: 123
----------------
YouTip