1. Общий обзор
В этом руководстве мы рассмотрим, как мы можем перейти с Java на Kotlin. Несмотря на то, что мы рассмотрим множество базовых примеров, эта статья не является введением в Kotlin. Что касается отдельной статьи, вы можете начать с этой записи здесь.
Здесь мы рассмотрим основные примеры переноса нашего Java-кода на Kotlin, такие как простые инструкции print, определение переменных, управление возможностью обнуления.
Затем мы перейдем к внутренним областям, таким как управляющие инструкции, такие как инструкции if-else и switch.
Наконец, мы переходим к определению классов и работе с коллекциями.
2. Основные миграции
Давайте начнем с простых примеров того, как переносить простые инструкции.
2.1. Распечатка выписок
Для начала давайте посмотрим, как работает печать. На Java:
System.out.print("Hello, Baeldung!");
System.out.println("Hello, Baeldung!");
В Котлине:
print("Hello, Baeldung!")
println("Hello, Baeldung!")
2.2. Определение переменных
На Java:
final int a;
final int b = 21;
int c;
int d = 25;
d = 23;
c = 21;
В Котлине:
val a: Int
val b = 21
var c: Int
var d = 25
d = 23
c = 21
Как мы видим, точки с запятой в Kotlin необязательны. Kotlin также использует расширенный вывод типов, и нам не нужно явно определять типы.
Всякий раз, когда мы хотим создать конечную переменную, мы можем просто использовать “val” вместо “var”.
2.3. Кастинг
В Java нам нужно выполнять ненужное приведение в действие в таких ситуациях, как:
if(str instanceof String){
String result = ((String) str).substring(1);
}
В Kotlin интеллектуальное приведение позволяет нам пропускать избыточное приведение:
if (str is String) {
val result = str.substring(1)
}
2.4. Битовые операции
Битовые операции в Kotlin гораздо более интуитивно понятны.
Давайте посмотрим на это в действии, на примере Java:
int orResult = a | b;
int andResult = a & b;
int xorResult = a ^ b;
int rightShift = a >> 2;
int leftShift = a << 2;
И в Котлине:
var orResult = a or b
var andResult = a and b
var xorResult = a xor b
var rightShift = a shr 2
var leftShift = a shl 2
3. Нулевая безопасность
На Java:
final String name = null;
String text;
text = null;
if(text != null){
int length = text.length();
}
Таким образом, в Java нет ограничений присваивать переменным значение null и использовать их. При использовании любой переменной мы обычно вынуждены также выполнять проверку значения null.
В Kotlin это не так:
val name: String? = null
var lastName: String?
lastName = null
var firstName: String
firstName = null // Compilation error!!
По умолчанию Kotlin предполагает, что значения не могут быть null.
Мы не можем присвоить null имени ссылки, и если мы попытаемся это сделать, это приведет к ошибке компилятора. Если мы хотим создать ссылку с возможностью обнуления, нам нужно добавить знак вопроса(?) к определению типа, как мы это сделали в первой строке.
4. Операции со строками
Строки работают так же, как и в Java. Мы также можем выполнять аналогичные операции, такие как добавление и получение части строки.
В Java:
String name = "John";
String lastName = "Smith";
String text = "My name is: " + name + " " + lastName;
String otherText = "My name is: " + name.substring(2);
String text = "First Line\n" +
"Second Line\n" +
"Third Line";
В Котлине:
val name = "John"
val lastName = "Smith"
val text = "My name is: $name $lastName"
val otherText = "My name is: ${name.substring(2)}"
val text = """
First Line
Second Line
Third Line
""".trimMargin()
Это выглядело довольно просто:
- Мы можем интерполировать строки, используя символ “$”, и выражения будут вычислены во время выполнения. В Java мы могли бы добиться чего-то подобного, используя String.format()
- Нет необходимости разбивать многострочные строки, как в Java. Kotlin поддерживает их "из коробки". Нам просто нужно помнить об использовании тройных кавычек
В Kotlin нет символа продолжения строки. Поскольку его грамматика допускает наличие пробелов почти между всеми символами, мы можем просто разорвать оператор:
val text = "This " + "is " + "a " +
"long " + "long " + "line"
Однако, если первая строка инструкции является допустимой, это не сработает:
val text = "This " + "is " + "a "
+ "long " + "long " + "line" // syntax error
Чтобы избежать подобных проблем при разбиении длинных инструкций на несколько строк, мы можем использовать круглые скобки:
val text = ("This " + "is " + "a "
+ "long " + "long " + "line") // no syntax error
5. Циклы и управляющие инструкции
Как и в любом другом языке программирования, в Kotlin также есть управляющие инструкции и циклы для повторяющихся задач.
5.1. Для цикла
В Java у нас есть различные виды циклов для итерации по коллекции или карте, например:
for (int i = 1; i < 11 ; i++) { }
for (int i = 1; i < 11 ; i+=2) { }
for (String item : collection) { }
for (Map.Entry<String, String> entry: map.entrySet()) { }
В Kotlin у нас есть нечто подобное, но более простое. Как мы уже знаем, синтаксис Kotlin пытается максимально имитировать естественный язык:
for (i in 1 until 11) { }
for (i in 1..10 step 2) { }
for (item in collection) { }
for ((index, item) in collection.withIndex()) { }
for ((key, value) in map) { }
5.2. Switch и When
Мы можем использовать операторы switch в Java для принятия выборочных решений:
final int x = ...; // some value
final String xResult;
switch (x) {
case 0:
case 11:
xResult = "0 or 11";
break;
case 1:
case 2:
//...
case 10:
xResult = "from 1 to 10";
break;
default:
if(x < 12 || x > 14) {
xResult = "not from 12 to 14";
break;
}
if(isOdd(x)) {
xResult = "is odd";
break;
}
xResult = "otherwise";
}
final int y = ...; // some value;
final String yResult;
if(isNegative(y)){
yResult = "is Negative";
} else if(isZero(y)){
yResult = "is Zero";
} else if(isOdd(y)){
yResult = "is Odd";
} else {
yResult = "otherwise";
}
В Kotlin вместо оператора switch мы используем оператор when для принятия выборочных решений:
val x = ... // some value
val xResult = when (x) {
0, 11 -> "0 or 11"
in 1..10 -> "from 1 to 10"
!in 12..14 -> "not from 12 to 14"
else -> if (isOdd(x)) { "is odd" } else { "otherwise" }
}
Оператор when может выступать в качестве выражения или инструкции, с аргументом или без него:
val y = ... // some value
val yResult = when {
isNegative(y) -> "is Negative"
isZero(y) -> "is Zero"
isOdd(y) -> "is odd"
else -> "otherwise"
}
6. Занятия
В Java мы определяем класс model и сопровождаем его стандартными установщиками и получателями:
package c
om.baeldung;
public class Person {
private long id;
private String name;
private String brand;
private long price;
// setters and getters
}
В Kotlin получатели и установщики генерируются автоматически:
package com.baeldung
class Person {
var id: Long = 0
var name: String? = null
var brand: String? = null
var price: Long = 0
}
Также можно изменить параметры видимости получателя/установщика, но имейте в виду, что видимость получателя должна совпадать с видимостью свойства.
В Kotlin каждый класс поставляется со следующими методами (которые могут быть переопределены):
- toString (читаемое строковое представление объекта)
- hashCode (предоставляет уникальный идентификатор для объекта)
- equals (используется для сравнения двух объектов из одного класса, чтобы определить, являются ли они одинаковыми)
7. Коллекции
Что ж, мы знаем, что коллекции - это мощная концепция для любого языка программирования; проще говоря, мы можем собирать объекты похожего типа и выполнять операции с ними. Давайте взглянем на них в Java:
final List<Integer> numbers = Arrays.asList(1, 2, 3);
final Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");
// Java 9
final List<Integer> numbers = List.of(1, 2, 3);
final Map<Integer, String> map = Map.of(
1, "One",
2, "Two",
3, "Three");
Теперь в Kotlin у нас могут быть похожие коллекции:
val numbers = listOf(1, 2, 3)
val map = mapOf(
1 to "One",
2 to "Two",
3 to "Three")
Выполнение операций также интересно, как и в Java:
for (int number : numbers) {
System.out.println(number);
}
for (int number : numbers) {
if(number > 5) {
System.out.println(number);
}
}
Далее, мы можем выполнить те же операции в Kotlin гораздо более простым способом:
numbers.forEach {
println(it)
}
numbers
.filter { it > 5 }
.forEach { println(it) }
Давайте рассмотрим последний пример о том, как собирать четные и нечетные числа в виде строки в качестве ключей и списка целых чисел в качестве их значений. В Java нам нужно будет написать:
final Map<String, List<Integer>> groups = new HashMap<>();
for (int number : numbers) {
if((number & 1) == 0) {
if(!groups.containsKey("even")) {
groups.put("even", new ArrayList<>());
}
groups.get("even").add(number);
continue;
}
if(!groups.containsKey("odd")){
groups.put("odd", new ArrayList<>());
}
groups.get("odd").add(number);
}
В Котлине:
val groups = numbers.groupBy {
if (it and 1 == 0) "even" else "odd"
}
8. Заключение
Эта статья служит начальной справкой при переходе с Java на Kotlin.
Оригинал статьи: https://www.baeldung.com/kotlin/java-to-kotlin