> For the complete documentation index, see [llms.txt](https://appsecurity.gitbook.io/devops/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://appsecurity.gitbook.io/devops/ppc/ppc-langs/backend/jvm/kotlin/basics.md).

# Basics

## Documentation

Документация (Language Guide): <https://kotlinlang.org/docs/reference/exceptions.html>

## Packages

```kotlin
package ctf.zone.pwn  
// Имя пакета указывается в начале исходного файла, так же как и в Java
// Но в отличие от Java, нет необходимости, чтобы структура пакетов совпадала со структурой папок: 
// исходные файлы могут располагаться в произвольном месте на диске.


import java.lang.IllegalStateException
import java.util.*
import java.io.File
```

## Vars, constants and comments

```kotlin
val PI = 3.14 // test comment
var global_var = 0

/* Блочный комментарий из
нескольких строк */
```

## Classes and Functions

### Functions

```kotlin
class KotlinClass {
    fun sum(a: Int, b: Int): Int {  // Функция принимает два аргумента Int и возвращает Int
        return a + b
    }

    fun sum(a: Int, b: Double) = a + b // Функция с выражением в качестве тела и автоматически определенным типом возвращаемого значения

    fun printSum(a: Int, b: Int): Unit {  // Функция, не возвращающая никакого значения (void в Java):
        print(a + b)
    }

    fun printSum(a: Int, b: Double) {  // Тип возвращаемого значения Unit может быть опущен
        print(a + b)
        println("jsfvkjsdfg")
    }

    fun variables() {
        // Неизменяемая (только для чтения) внутренняя переменная
        val a: Int = 1
        val b = 1   // Тип `Int` выведен автоматически
        val c: Int  // Тип обязателен, когда значение не инициализируется
        c = 1       // последующее присвоение


        // Изменяемая переменная
        var x = 5 // Тип `Int` выведен автоматически
        x += 1

        // Изменение глобальных переменных
        global_var += 1
    }
}
```

### Static Functions

```kotlin
// Static functions
class MainActivity : AppCompatActivity() {
    companion object {
        // PARAM_RESULT — Static Field
        val PARAM_RESULT: String = "com.zfr.network.extra.RESULT" 
        fun test() {
            
        }
    }    
}
```

### Extensions

Это функции-расширения

```kotlin
// Функции-расширения
fun String.spaceToCamelCase() { return }
"Convert this to camelcase".spaceToCamelCase()
```

### Возвращение нескольких типов данных из функций

Создавать sealed классы: <https://kotlinlang.org/docs/reference/sealed-classes.html>

Если надо ветвить логику - на исключениях

## Strings

### Шаблоны

```kotlin
fun string_patterns(args: Array<String>, test: Any) {
        /*
        Допустимо использование переменных внутри строк в формате $name или ${name}
         */
        if (args.size == 0) return
        else print("kjkfgd")

        print("Первый аргумент: ${args[0]}")

        var a = 1
        // просто имя переменной в шаблоне:
        val s1 = "a равно $a"

        a = 2
        // произвольное выражение в шаблоне:
        val s2 = "${s1.replace("равно", "было равно")}, но теперь равно $a"

        /*
          Результат работы программы:
          a было равно 1, но теперь равно 2
        */
}
```

### Дополнить строку символами

```kotlin
val name = "Barsik"
val pad = name.padStart(10, '#')
println(pad) // ####Barsik

val name = "Barsik"
val pad = name.padEnd(10, '*')
println(pad) // Barsik****
```

### Подстроки

```kotlin
// подстрока с указанного индекса
val result = "developer.alexanderklimov.ru".substring(10) // alexanderklimov.ru

// подстрока до первого указанного разделителя
val first = "developer.alexanderklimov.ru".substringBefore('.') // developer

// подстрока после первого указанного разделителя
val last = "developer.alexanderklimov.ru".substringAfter('.') // alexanderklimov.ru

// подстрока после последнего указанного разделителя
val last = "developer.alexanderklimov.ru".substringAfterLast('.') // ru

// подстрока до последнего указанного разделителя
val beforeLast = "developer.alexanderklimov.ru".substringBeforeLast('.') // developer.alexanderklimov
```

### Встроенные функции

```kotlin
val blank = "   ".isBlank() // true, если пустая строка или пустые символы пробела, табуляции и т.п.

// индекс последнего символа
val lastIndex = "Кот Мурзик".lastIndex // 9

// переводим в верхний регистр первый символ строки
// decapitalize() выполняем обратную задачу
val capitalize = "кот Мурзик".capitalize()

val withSpaces = "1".padStart(2) // добавляем пробел перед строкой
val endZeros = "1".padEnd(3, '0') // "100"  добавляем нули в конец

val dropStart = "Kotlin".drop(2) // "tlin" убираем первые символы в указанном количестве
val dropEnd = "Kotlin".dropLast(3) // "Kot" убираем последние символы в указанном количестве

// возвращаем строку без первого символа, который удовлетворяет условию
val string = "Мурзик"
val result = string.dropWhile{
    it == 'М'
}
textView.text = result // урзик

// возвращаем строку без последнего символа, который удовлетворяет условию
val string = "Мурзик"
val result = string.dropLastWhile{
    it == 'к'
}
textView.text = result // Мурзи

// разбиваем на массив строк
"A\nB\nC".lines() // [A, B, C]
"ABCD".zipWithNext() // [(A, B), (B, C), (C, D)]

// удаляем символы из заданного диапазона
val string = "Кот, который гулял сам по себе"
val result = string.removeRange(
    3..28 // range
)

// удаляем префикс из строки
val string = "Кот, который гулял сам по себе"
val result = string.removePrefix("Кот")

// удаляем суффикс из строки
val string = "Кот, который гулял сам по себе"
val result = string.removeSuffix("себе")

// удаляем заданный разделитель, который должен окружать строку с начала и с конца
val string = "та, тра-та-та, мы везём с собой кота"

val result = string.removeSurrounding(
    "та" // delimiter
)

textView.text = result // , тра-та-та, мы везём с собой ко

// Также можно указать разные начало и конец, которые окружают строку
val string = "Тра-та-та, тра-та-та, мы везём с собой кота"

val result = string.removeSurrounding(
    "Тра-", // prefix
    " кота" // suffix
)

textView.text = result // та-та, тра-та-та, мы везём с собой


// Добавляем отступы при явном переводе на новую строку
val string = "Какой-то длинный текст, \nсостоящий из имён котов: " +
        "\nВаська" +
        "\nБарсик" +
        "\nРыжик"

val result = string.prependIndent(
    "     " // indent
)

// Разбиваем символы на две группы. 
// В первую группу попадут символы в верхнем регистре, во вторую - символы в нижнем регистре
val string = "Кот Васька и кот Мурзик - Друзья!"

val result: Pair<String, String> = string.partition {
    it.isUpperCase()
}

textView.text = result.first + ":" + result.second //КВМД:от аська и кот урзик - рузья!

// Разбиваем строку на список строк. В качестве разделителя - перевод на новую строку
val string = "Кот Васька\nКотМурзик\nКот Мурзик"

// Split string into lines (CRLF, LF or CR)
val lines: List<String> = string.lines()

textView.text = "Кол-во строк: ${lines.size}"
lines.forEach {
    textView.append("\n" + it)
}

// Разбиваем строку на список строк с указанным числом символов. В последней строке может выводиться остаток
val string = "Тра-та-та, тра-та-та, мы везём с собой кота"
val list:List<String> = string.chunked(11)
list.forEach {
    textView.append("$it\n")
}

/*
Тра-та-та, 
тра-та-та, 
мы везём с 
собой кота
*/

// Содержит ли строка только цифры (используем предикат)
val string = "09032020"

// Returns true if all characters match the given predicate.
val result: Boolean = string.all{
    it.isDigit()
}
textView.append("Is the string $string contain only digit? $result")

// Содержит ли строка хотя бы одну цифру (используем предикат)
val string = "3 кота"
// Returns true if at least one character matches the given predicate.
val result: Boolean = string.any() {
    it.isDigit()
}
textView.append("Is the text \"$string\" contain any digit? $result")

// Сравниваем две строки с учётом регистра
val string1 = "This is a sample string."
val string2 = "This is a SAMPLE string."

if (string1.compareTo(string2, ignoreCase = true) == 0) {
    textView.append("\n\nBoth strings are equal, ignoring case.")
} else {
    textView.append("\n\nBoth strings are not equal, ignoring case.")
}
```

Можно фильтровать данные с помощью **filter()**. Допустим, мы хотим извлечь только цифры из строки.

```

val string = "9 жизней (2016) - Nine Lives - информация о фильме"
val filteredText = string.filter { it.isDigit() }
textView.text = filteredText // 92016
```

Если хочется решить обратную задачу и получить только символы, но не цифры - то достаточно вызвать **filterNot()**.

```

val filteredText = string.filterNot { it.isDigit() }
```

### String -> Hex String

```kotlin
fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }

var someString = "test"
val result = someString.toByteArray().toHexString()
```

## Циклы, ветвления, групповые операции

```kotlin
// Использование циклов
for (arg in args)
    print(arg)

for (i in args.indices)
    print(args[i])

var i = 0
while (i < args.size) {
    print(args[i++])
}

// Использование switch (здесь он when называется)
when (test) {
    1 -> print("123")
    "Hello" -> print("jvcbsdjfv")
    is Long -> print("sjkdvnksdv")
    !is String -> print("sdfsdg")
    else -> print("Unknown")
}

// Использование интервалов
if (i in 1..5)
    print("OK")
if (i !in 1..5)
    print("FAIL")
for (i in 1..5 step 1)
    print(i)
    
// триарные операторы
fun max(a: Int, b: Int) = if (a > b) a else b

// return с оператором when
val color = "sfgsdg"
var test = when (color) {
    "Red" -> 0
    "Green" -> 1
    "Blue" -> 2
    else -> throw IllegalArgumentException("Invalid color param value")
}

// try/catch
val result = try {
    print("lkdfjvlkdfjvlkdfg")
} catch (e: ArithmeticException) {
    throw IllegalStateException(e)
}

// Вызов нескольких объектов через with
/*
class Turtle {
    fun penDown()
    fun penUp()
    fun turn(degrees: Double)
    fun forward(pixels: Double)
}

val myTurtle = Turtle()
with(myTurtle) { //draw a 100 pix square
    penDown()
    for(i in 1..4) {
        forward(100.0)
        turn(90.0)
    }
    penUp()
}
*/
```

## Nullable

```kotlin
1. Elvis operator "?:" - вернет значение или сделает действие (return)
test = value ?: return

2. Use safee call - выполнится если не null
left?.let { node -> queue.add(node) }
left?.let { queue.add(it) }
left?.let(queue::add)

3. 
```

```kotlin
// Nullable-значения и проверка на null
fun var_null_and_check(str: Any): Int? {
    // Возвращает null если str не содержит числа
    // Ссылка должна быть явно объявлена как nullable (символ ?) когда она может принимать значение null.
    val x = null
    if (str is String || str == null)
        return 1
        //return str.length
    else {
        if (str !is String)
            return 1
        return 0
    }
}
```

```kotlin
// Сокращение для "Если не null"
val files = File("Test").listFiles()
println(files?.size)

// Сокращение для "Если не null, иначе"
println(files?.size ?: "empty")

// Вызов оператора при равенстве null
/*
val email = name["email"] ?: throw IllegalStateException("Email is missing!")
*/

// Выполнение при неравенстве
/*
val data = ...

data?.let {
    ... // execute this block if not null
}
*/

```

## Коллекции

```kotlin
fun collections() {
        val items = setOf("apple", "banana", "kiwi")
        // Использование лямбда-выражения для фильтрации и модификации коллекции
        items
            .filter { it.startsWith("A") }
            .sortedBy { it }
            .map { it.toUpperCase() }
            .forEach { print(it) }

        // Read-only ассоциативный список (map)
        var map = mapOf("a" to 1, "b" to 2, "c" to 3)

        // Итерация по карте/списку пар
        for ((k, v) in map) {
            println("$k -> $v")
        }

        // Обращение к списку
        println(map["key"])

        // read-only list
        val list = listOf("a", "b", "c")
    }
```

## Ленивые свойства

Будут вычислены при обращении

```kotlin
// Ленивые свойства
val p: String by lazy {
    // compute the string
    return@lazy "sdfsdf"
}
```

## Синглтон

```kotlin
// Создание синглтона
/*
object Resource {
    val name = "Name"
}
*/
```

## Reflection

Получить Type или Class

```kotlin
val type = object : TypeToken<MyErrorData>(){}.type
val klass = MyErrorData::class
где-то еще такое видел:
val klass = MyErrorData::class.java
val klass = MyErrorData.class
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://appsecurity.gitbook.io/devops/ppc/ppc-langs/backend/jvm/kotlin/basics.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
