Привіт, студент JavaRush, поки тебе цілком і повністю не поглинула Java, я хотів би розширити твій кругозір і звернути увагу на мову Kotlin , що набирає популярності !
Kotlin - досить молода мова, розроблена компанією JetBrains . Так-так, саме тією компанією, яка розробила нашу улюблену IDE: IntelliJ IDEA. Kotlin є JVM мовою і повністю сумісний з Java , тобто з Kotlin-коду можна без проблем звертатися до звичних Java-бібліотеків, Та що там до бібліотек: Kotlin та Java класи можуть вживатися в одному package! Kotlin настільки сподобався спільноті програмістів, що Google визнав його офіційною мовою розробки під Android, а останнім часом Kotlin почав набирати популярності і в ентерпрайз-проектах. У цій статті я хотів би навести кілька порівняльних прикладів коду, написаного на Kotlin і Java, і зробити деякі висновки. Поїхали! Почнемо за традицією з "Hello World"
// Java
public class Application {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
// Kotlin
class Application
fun main(vararg args: String) {
println("Hello World!")
}
Дивлячись на приклад Kotlin, можна відразу відзначити таке:
- не потрібно писати крапку з комою в кінці рядка;
- всі методи описуються ключовим словом fun ;
- щоб вивести рядок достатньо одного слова - println() !
// Java (до 10)
final Application application = new Application();
// Kotlin
val application = Application()
Відмінності Kotlin:
- не потрібно оголошувати тип змінної, якщо він зрозумілий за екземпляром;
- замість типу змінної - val (незмінна) або var (змінна);
- для створення екземпляра не потрібно писати ключове слово new !
// Java
public int sum(int a, int b) {
return (a + b);
}
// Kotlin
fun sum(a: Int, b: Int): Int {
return (a + b)
}
Відмінності Kotlin:
- якщо з методу потрібно щось повернути, в сигнатуру додається " : Int ", де Int - тип, що повертається;
- опис параметрів методу: спочатку ім'я змінної, потім тип;
- Оскільки тіло методу складається всього з одного рядка, можна опустити return :
fun sum(a: Int, b: Int): Int = (a+b)
// Java
public int sum(int a, int b) {
int result = (a + b);
System.out.printf("Сумма %d и %d равна %d\n", a, b, result);
return result;
}
// Kotlin
fun sum(a: Int, b: Int): Int {
val result = (a + b)
println("Сумма $a и $b равна $result")
return result
}
Kotlin підтримує інтерполяцію рядків, достатньо використовувати символ "$" спочатку змінної. Такий запис значно підвищує чистоту та читабельність коду. Порівняння екземплярів
// Java
object1.equals(object2)
// Kotlin
object1 == object2
У Kotlin порівняння ==
для об'єктних типів транслюється в equals
! Для порівняння посилань використовується " ===
" . Винятки
// Java
public List<String> getFileContent(String file) throws IOException {
Path path = Paths.get(file);
return Files.readAllLines(path);
}
// Kotlin
fun getFileContent(file: String): List<String> {
val path = Paths.get(file)
return Files.readAllLines(path)
}
У Kotlin немає checked винятків, тепер не потрібно нескінченно прокидати виняток через всю програму або городити багаторівневі try-catch
. Null Safety
// Java
public class Data {
String value;
String render() {
if (value == null) {
return "Value: undefined";
} else {
return "Value:" + value.toUpperCase();
}
}
}
// Kotlin
class Data {
var value: String? = null
fun render(): String =
"Value: ${value?.toUpperCase() ?: "undefined"}"
}
У Kotlin перейнялися проблемою NPE і ввели низку вимог:
- всі поля класу та змінні обов'язково повинні бути проініціалізовані;
- у полі чи змінну можна записати "null", але тоді ти зобов'язаний явно сказати, що твоя змінна Nullable (написати знак "?");
- елвіс-оператор "?:" працює наступним чином: якщо зліва Null, візьми те, що вказано праворуч. У разі нашого прикладу, коли змінна value не проініціалізована, візьметься значення " undefined " .
// Java
public class Data {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
class App {
void execute() {
Data data = new Data()
data.setValue("Foo")
}
}
// Kotlin
class Data {
var value: String = ""
}
class App {
fun execute() {
val data = Data()
data.value = "Foo" // Под капотом выполнится data.set("Foo")
}
}
У Kotlin досить просто описати поле і все: у нього вже є неявні гетери та сеттери (привіт lombok ), які за бажання будь-якої миті можна перевизначити. При цьому читаємо та модифікуємо значення поля просто звертаючись безпосередньо до нього, а під капотом викликається get()|set()
. Цикли
// Java
void example() {
for(int i = 1; i <= 10; i++) {
System.out.println(i);
}
for(String line : "a,b,c".split(",")) {
System.out.println(line);
}
}
// Kotlin
fun example() {
for(i in 1..10) {
println(i)
}
for(line in "a,b,c".split(",")) {
println(line)
}
}
Kotlin надав зручний та одноманітний синтаксис обходу послідовностей: ти просто використовуєш зліва змінну, праворуч послідовність, а між ними – ключове слово " in ", тип визначається автоматично за вмістом. Сінглтон
// Java
public class Singleton {
private static Singleton ourInstance = new Singleton();
public static Singleton getInstance() {
return ourInstance;
}
private Singleton() {
}
}
class App {
void execute() {
Singleton singleton = Singleton.getInstance()
}
}
// Kotlin
object Singleton {}
class App {
fun execute() {
val singleton = Singleton
}
}
Знайомий всім патерн " одиначка " досить часто використовується на практиці, тому в Kotlin вирішабо створити окреме ключове слово " object ", яке пишеться замість " class " і означає, що клас є синглтоном, при використанні навіть не потрібно звати конструктор або будь-які інші методи! Іменовані параметри методів та дефолтні значення
// Java
void setStatus(String code) {
setStatus(code, "");
}
void setStatus(String code, String desc) {
this.code = code;
this.desc = desc;
}
// Kotlin
fun setStatus(code: String, desc: String = "") {
this.code = code;
this.desc = desc;
}
fun execute() {
setStatus("200")
setStatus(code = "200", desc = "Ok")
}
Трапляється таке, що не всі параметри в методі або конструкторі повинні бути обов'язковими, і Java ми звикли створювати набір методів або конструкторів під комбінацію параметрів. У Kotlin ввели дефолтні параметри, що дозволяє оголосити один метод і передавати в нього необхідний набір параметрів ситуації. Стрими
// Java
String getFirst(List<String> strings, String alpha) {
return strings.stream()
.filter(x -> x.startsWith(alpha))
.findFirst()
.orElse("");
}
// Kotlin
fun getFirst(strings: List<String>, alpha: String): String {
return strings.first { it.startsWith(alpha) }
}
Stream в Java 8 стали невід'ємним функціоналом при роботі з колекціями. У Kotlin стрими зробабо ще зручнішими і функціональнішими: кожна колекція вже має набір зручних часто використовуваних методів для роботи з даними. Крім того, зверніть увагу на лямбда вираз усередині методу first: якщо функціональний літерал має рівно один параметр, його оголошення можна видалити (разом з ->), і звертатися до нього на ім'я it . Настав час закруглюватися... Я продемонстрував лише малу, базову частину функціоналу, але, я впевнений, тобі вже захотілося спробувати Kotlin! За своїм досвідом я можу зробити такі висновки:
- Java розробнику дуже легко освоїти синтаксис Kotlin та почати писати код;
- у Kotlin повна сумісність з Java, і його вже можна пробувати у своїх проектах, що діють, наприклад, у тестах;
- код на Kotlin чистіший і читабельніший, не потрібно писати купу бойлерплейта ;
- у IDEA є автоматичний конвертер Java у Kotlin, ви можете брати готовий Java-код і автоматично конвертувати його у Kotlin;
- новий проект потрібно писати на Kotlin, тому що з інфраструктурної точки зору це та ж Java, а по використанню краще і зручніше!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ