Предлагаю начать с общих черт.
Java и Kotlin являются языками со статической типизацией. Это означает, что проверка типов выполняется во время компиляции. (Существуют также языки с динамической типизацией, например PHP, Python и JavaScript.)
Это хорошо видно из примера ниже.
Оба языка являются бесплатными и распространяются как открытое программное обеспечение (можно использовать без ограничений и участвовать в развитии).
3. Байт-код
Оба языка преобразуют код в байт-код, исполняемый JVM.
4. Интероперабельность
Оба языка являются интероперабельными. Это означает, что файлы Java и Kotlin могут сосуществовать в одном проекте или пакете JAR.
5. Поддержка ООП
Оба являются объектно-ориентированными языками программирования.
(Таким образом, они поддерживают основные концепции ООП)
Полиморфизм, наследование, инкапсуляция, абстракция.
А теперь рассмотрим основные отличия.
1. Представление публике и релиз
5. Доля рынка
https://www.statista.com/statistics/793628/worldwide-developer-survey-most-used-languages/
https://insights.stackoverflow.com/survey/2020#most-popular-technologies
https://insights.stackoverflow.com/survey/2020#most-loved-dreaded-and-wanted
6. Безопасная работа с обнуляемыми переменными (null safety)
val name: String = null //Error because not possible to assign a null value
Nullable-типы используются с оператором безопасного вызова.
name?.getLength()
Таким образом, даже если name примет значение null, все выражение будет эквивалентно null без возникновения NullPointerException.
7. Гибридные приложения
println(“hello”)
}
2. Поведение по умолчанию
final class B { … } in Java is equal to class B { …} in Kotlin.
— это одно и то же в Kotlin.
В Kotlin используется четыре модификатора видимости: private, protected, public и internal.
Internal подразумевает повсеместную видимость в одном модуле.
public default void myMethod() {
System.out.println(“D”);
}
} /Allowed
var website = “hello”
var website: String = “hello” //одно и то же
//Указывать тип обязательно, если вначале идет объявление, а потом инициализация
var website: String
website = “hello“
Нельзя сравнивать типы разной величины.
val a: Int = 10; val b: Long = 10L
print(a == b) // Ошибка в Kotlin: сравнение невозможно. В Java возвращается true.
val num:Integer = 10 //не будет работать
Массивы объявляются следующим образом:
Int[] numbers = new int[] {10,20,30,40,50}
val numbers = intArrayOf(10,20,30,40,50)
val numbers = arrayOf(10,20,30,40,50)
var numbers = IntArray(5){it*10}
var numbers = Array<Int>(5){it*10}
4. Списки
Тип List по умолчанию в Kotlin является неизменяемым, поэтому методы add() или remove() работают не так, как в Java.
val lst = listOf<Int>(10, 20, 30, 40, 50)
lst.add(60) //Ошибка
val lst2 = mutableListOf<Int>(10, 20, 30, 40, 50) //то же самое, что ArrayList<Int>
// val для mutableList? Да, потому что нового присваивания не происходит, только изменение содержимого.
lst2.add(60) //OK
lst2 += 70 //тоже OK
Оперировать списком в языке Kotlin можно с помощью функций take и drop.
val nums = listOf(0,1,2,3,4,5,6,7)
nums.take(3) // [0,1,2]
nums.drop(3) // [3,4,5,6,7]
5. Циклы
В Kotlin доступно несколько вариантов циклов for. В Java последний имеет фиксированную структуру.
val lst : List<Int> = listOf<Int>(10, 20, 30, 40, 50)
for(item in lst){
println(item)
}
for(item in 0 until lst.size){
println(lst[item])
}
for(item in 0..4){ //оператор диапазона (range)
println(lst[item])
}
В заключение предлагаю рассмотреть функциональные различия.
fun main(args: Array<String>) {
val per1 = Person(“amir”) //вызов только первичного конструктора
val per2 = Person(“ansari”,20, ‘A’) //если убрать ‘A’ , вторичный конструктор не вызывается, //так как нет значения по умолчанию для blood_group
}
Вторичный конструктор должен расширять поведение первичного конструктора.
class Person (var name: String, var age: Int = 18) {
init{
println(“Student has got a name as $name and age as $age”)
}
var blood_group: Char = ‘O’
constructor(_name: String, age: Int, blood_group: Char) : this(_name, age) {
this.blood_group = blood_group
println(“Student name= $_name and age= $age and blood group=$blood_group”)
}
}
2. Функции-расширения
return this.count { c -> c == ‘ ‘ }
}
3. Функции высшего порядка
В языке Kotlin функция, которая может принимать в качестве параметра функцию или лямбда-выражение или же может возвращать функцию, называется функцией высшего порядка (higher-order function).
// лямбда-выражение
var lambda = {a: Int , b: Int -> a + b }
//функция высшего порядка
fun highfun( lmbd: (Int, Int) -> Unit) { // принимает лямбда-выражение как параметр, ничего не возвращает
var result = lmbd(2,4) // вызывает лямбда-выражение, передавая ему параметры
println(“Сумма двух чисел равна $result”)
}
fun main() {
highfun(lambda) //лямбда-выражение передается как параметр
}
4. Data-классы
— это все!
5. Статические члены
Как только мы объявляем переменную static, она загружается в память во время компиляции, то есть доступна только одна ее копия. Одиночки (signgleton) и статические члены имеют схожее поведение.
Ключевое слово static делает компонент частью класса, не связанной с объектом этого класса.
В концепции ООП то, что не является объектом, существовать не должно.
В Java все должно объявляться внутри класса. Но в Kotlin все иначе. Компоненты могут объявляться за пределами класса, и это автоматически делает их статическими. Поэтому нам не требуется ключевое слово static.
В Java статические члены обрабатываются не так, как члены-объекты. Это означает, что для статических членов нам недоступны такие вещи, как реализация интерфейса, помещение экземпляра в ассоциативный список (map) или передача его в качестве параметра методу, который принимает объект.
В Kotlin static не является ключевым словом и вместо статических членов используются объекты-компаньоны, позволяющие преодолеть вышеуказанные ограничения.
В Java существует множество решений для асинхронной работы: RxJava, AsyncTask (уже официально не поддерживается), обработчики, обратные вызовы...
Наряду со всеми этими возможностями в Kotlin также имеются корутины (coroutines, также их называют сопрограммами), которые упрощают работу.
Корутины (или легковесные потоки) не являются отдельными потоками, но несколько корутин могут совместно использовать один поток.
7. Проверяемые исключения
Такие исключения, как IOException и FileNotFoundException, присутствуют в Java, но не поддерживаются в Kotlin.
В Kotlin модификаторы lateinit и by Lazy позволяют инициализировать значения до их фактического использования.
val myUtil by lazy {
MyUtil(parameter1, parameter2)
}
lateinit var myUtil: MyUtil
Вышеприведенный код инициализирует объект MyUtil. Но это будет сделано только при первом использовании myUtil.
Оба варианта служат одной цели, но по факту сильно отличаются. Один является неизменяемым (val), другой — изменяемым (var).
@Injectlateinit var myUtil: MyUtil
if (foo::bar.isInitialized) {
println(foo.bar)
}
Переменная lateinit может быть инициализирована из любого места, откуда доступен объект.
В свою очередь, Java не поддерживает отложенную инициализацию, поэтому значения инициализируются, даже если они не используются.
Вот некоторые различия между этими двумя мощными языками.
Благодарю за внимание!
- Статическая типизация
- Бесплатны и с открытым кодом
- Код преобразуется в байт-код
- Интероперабельность
- Объектно-ориентированные языки программирования
Java и Kotlin являются языками со статической типизацией. Это означает, что проверка типов выполняется во время компиляции. (Существуют также языки с динамической типизацией, например PHP, Python и JavaScript.)
Это хорошо видно из примера ниже.
Оба языка являются бесплатными и распространяются как открытое программное обеспечение (можно использовать без ограничений и участвовать в развитии).
3. Байт-код
Оба языка преобразуют код в байт-код, исполняемый JVM.
4. Интероперабельность
Оба языка являются интероперабельными. Это означает, что файлы Java и Kotlin могут сосуществовать в одном проекте или пакете JAR.
5. Поддержка ООП
Оба являются объектно-ориентированными языками программирования.
(Таким образом, они поддерживают основные концепции ООП)
Полиморфизм, наследование, инкапсуляция, абстракция.
А теперь рассмотрим основные отличия.
1. Представление публике и релиз
- Язык Java был разработан компанией Sun Microsystems (в настоящее время принадлежит Oracle) в 1995 году.
- Он поддерживается практически всеми типами устройств и операционных систем, будь то Android, Windows или Linux.
- Язык Kotlin был представлен компанией JetBrains в 2011 году, выложен в открытый доступ в 2012 году, официально поддержан на Google I/O (ежегодном мероприятии разработчиков Google) в 2017 году.
- По заявлению Google, 70 % из 1000 лучших приложений для Android сейчас написаны на Kotlin.
- Некоторые приложения пока находятся в процессе переноса с Java на Kotlin, например приложение Google Home еще не полностью переписано на Kotlin...
- ...но по состоянию на июнь 2020 года около 30 % старой кодовой базы на Java уже было переписано на Kotlin.
- Другими популярными примерами Kotlin-приложений от Google являются Maps, Play и Drive.
- Прочие компании также выпустили множество приложений для Android, написанных на языке Kotlin.
- Сейчас при поддержке разработки под Android компания Google придерживается стратегии «Kotlin прежде всего». Это в чем-то похоже на ситуацию с разработкой приложений под iOS, где произошел переход от Objective-C к Swift.
- По состоянию на ноябрь 2020 года актуальной версией Kotlin является 1.4.0.
- Несмотря на выход Java 15, самой популярной версией все еще остается Java 8 (или 1.8).
- По этому параметру Java превосходит Kotlin на 12–15 % для чистых сборок (то есть в этом случае Kotlin компилируется немного медленнее).
- Однако в случае частичных сборок с включенной инкрементной компиляцией (то есть с компиляцией только небольших изменений) Kotlin компилируется так же быстро, как и Java, или даже немного быстрее.
- Код, написанный на Kotlin, намного компактнее по сравнению с Java — на 30–40 %.
Таким образом, в теории размер приложений может уменьшиться на треть. - Язык Java — крайне многословный, а Kotlin — лаконичный и современный.
5. Доля рынка
- По данным опросов, разработчиков на Kotlin примерно в пять раз меньше, чем использующих Java.
- 7,8 % разработчиков предпочитают Kotlin, более чем 40 % — Java. Однако эти опросы также показывают, что Kotlin нравится программистам больше, чем Java, и быстро наращивает аудиторию.
https://www.statista.com/statistics/793628/worldwide-developer-survey-most-used-languages/
https://insights.stackoverflow.com/survey/2020#most-popular-technologies
https://insights.stackoverflow.com/survey/2020#most-loved-dreaded-and-wanted
6. Безопасная работа с обнуляемыми переменными (null safety)
- Kotlin защищен от NullPointerException. Именно этот тип ошибки является самой частой причиной сбоев приложений из Google Play.
- Java позволяет разработчикам присваивать значение null любой переменной.
- В отличие от Java, в Kotlin по умолчанию все типы являются non-nullable, то есть не могут принимать значение null. Присвоение или возврат null приведет к ошибке компиляции.
- Чтобы присвоить переменной значение null, в Kotlin необходимо явно пометить эту переменную как nullable.
val name: String = null //Error because not possible to assign a null value
Nullable-типы используются с оператором безопасного вызова.
name?.getLength()
Таким образом, даже если name примет значение null, все выражение будет эквивалентно null без возникновения NullPointerException.
7. Гибридные приложения
- Kotlin можно использовать для написания нативных приложений для Android и iOS.
- Kotlin Multiplatform Mobile (KMM) работает в Android и iOS.
- Java до последнего времени не использовалась при разработке приложений под iOS.
- Функция main
- В Java метод main должен размещаться внутри класса. Он объявляется как статический метод.
- В Kotlin, чтобы сделать функцию статической, достаточно поместить ее на уровень пакета. Так что это может быть самостоятельная функция без класса.
- Аргументы метода main в Kotlin можно опустить, если наша программа не должна принимать аргументы командной строки.
println(“hello”)
}
- В Java, если мы не включаем аргументы в функцию main (даже если мы их не используем), выводится ошибка.
2. Поведение по умолчанию
- В отличие от Java, по умолчанию классы в Kotlin являются финальными (final), поэтому, чтобы разрешить наследование от класса, его следует пометить ключевым словом open.
- Чтобы разрешить переопределение метода, его необходимо явно пометить как open.
final class B { … } in Java is equal to class B { …} in Kotlin.
- В Kotlin все, что не имеет модификаторов доступа, по умолчанию является public. Мы можем явно прописать public в определении, но это не обязательно.
— это одно и то же в Kotlin.
В Kotlin используется четыре модификатора видимости: private, protected, public и internal.
Internal подразумевает повсеместную видимость в одном модуле.
- В Java используется ключевое слово default.
- Ключевое слово default является модификатором доступа. Если вы не назначили переменным, методам, конструкторам и классам какой-либо модификатор доступа, то по умолчанию используется модификатор доступа default.
- Default обеспечивает видимость в пределах пакета.
- Методы с модификатором default позволяют добавлять в интерфейсы новые функциональные возможности.
public default void myMethod() {
System.out.println(“D”);
}
} /Allowed
- В Kotlin ключевое слово default не используется.
- Изменяемым (mutable) и неизменяемым (immutable) типами в Kotlin являются var и val
var website = “hello”
var website: String = “hello” //одно и то же
//Указывать тип обязательно, если вначале идет объявление, а потом инициализация
var website: String
website = “hello“
- В числовых литералах разрешается использовать символы подчеркивания.
Нельзя сравнивать типы разной величины.
val a: Int = 10; val b: Long = 10L
print(a == b) // Ошибка в Kotlin: сравнение невозможно. В Java возвращается true.
- Имена примитивных типов данных в Kotlin начинаются с заглавной буквы, например Boolean и Int, в то время как в Java — со строчной, например char и double.
- Классы-обертки, такие как Integer, доступны в обоих языках.
val num:Integer = 10 //не будет работать
Массивы объявляются следующим образом:
Int[] numbers = new int[] {10,20,30,40,50}
val numbers = intArrayOf(10,20,30,40,50)
val numbers = arrayOf(10,20,30,40,50)
var numbers = IntArray(5){it*10}
var numbers = Array<Int>(5){it*10}
4. Списки
Тип List по умолчанию в Kotlin является неизменяемым, поэтому методы add() или remove() работают не так, как в Java.
val lst = listOf<Int>(10, 20, 30, 40, 50)
lst.add(60) //Ошибка
val lst2 = mutableListOf<Int>(10, 20, 30, 40, 50) //то же самое, что ArrayList<Int>
// val для mutableList? Да, потому что нового присваивания не происходит, только изменение содержимого.
lst2.add(60) //OK
lst2 += 70 //тоже OK
Оперировать списком в языке Kotlin можно с помощью функций take и drop.
val nums = listOf(0,1,2,3,4,5,6,7)
nums.take(3) // [0,1,2]
nums.drop(3) // [3,4,5,6,7]
5. Циклы
В Kotlin доступно несколько вариантов циклов for. В Java последний имеет фиксированную структуру.
val lst : List<Int> = listOf<Int>(10, 20, 30, 40, 50)
for(item in lst){
println(item)
}
for(item in 0 until lst.size){
println(lst[item])
}
for(item in 0..4){ //оператор диапазона (range)
println(lst[item])
}
В заключение предлагаю рассмотреть функциональные различия.
- Конструкторы
- В Kotlin доступны два вида конструкторов.
- Один из них прописывается после имени класса и называется первичным конструктором, а второй прописывается в теле класса и называется вторичным конструктором.
- В классе могут быть один первичный конструктор и несколько вторичных.
val per1 = Person(“amir”) //вызов только первичного конструктора
val per2 = Person(“ansari”,20, ‘A’) //если убрать ‘A’ , вторичный конструктор не вызывается, //так как нет значения по умолчанию для blood_group
}
Вторичный конструктор должен расширять поведение первичного конструктора.
class Person (var name: String, var age: Int = 18) {
init{
println(“Student has got a name as $name and age as $age”)
}
var blood_group: Char = ‘O’
constructor(_name: String, age: Int, blood_group: Char) : this(_name, age) {
this.blood_group = blood_group
println(“Student name= $_name and age= $age and blood group=$blood_group”)
}
}
2. Функции-расширения
- Kotlin позволяет разработчикам расширять класс, добавляя новую функциональность при помощи функций-расширений.
- Это поистине замечательное улучшение, поскольку программисту не требуется расширять класс.
- По сути, функция-расширение — это функция, которая является членом класса, но определена за его пределами.
- В Java функций-расширений не было.
return this.count { c -> c == ‘ ‘ }
}
3. Функции высшего порядка
В языке Kotlin функция, которая может принимать в качестве параметра функцию или лямбда-выражение или же может возвращать функцию, называется функцией высшего порядка (higher-order function).
// лямбда-выражение
var lambda = {a: Int , b: Int -> a + b }
//функция высшего порядка
fun highfun( lmbd: (Int, Int) -> Unit) { // принимает лямбда-выражение как параметр, ничего не возвращает
var result = lmbd(2,4) // вызывает лямбда-выражение, передавая ему параметры
println(“Сумма двух чисел равна $result”)
}
fun main() {
highfun(lambda) //лямбда-выражение передается как параметр
}
4. Data-классы
- В больших проектах, как правило, используется несколько классов, предназначенных исключительно для хранения данных.
- Разработчику на Java приходится писать много стандартного, но часто встречающегося кода (так называемый шаблонный код или boilerplate), data-классы в Kotlin позволяют избежать этих дополнительных усилий.
- В Java-классе для этой цели должны присутствовать геттеры и сеттеры, функции Hashcode(), toString() и equals(). Эквивалентом в Kotlin будет...
— это все!
5. Статические члены
Как только мы объявляем переменную static, она загружается в память во время компиляции, то есть доступна только одна ее копия. Одиночки (signgleton) и статические члены имеют схожее поведение.
Ключевое слово static делает компонент частью класса, не связанной с объектом этого класса.
В концепции ООП то, что не является объектом, существовать не должно.
В Java все должно объявляться внутри класса. Но в Kotlin все иначе. Компоненты могут объявляться за пределами класса, и это автоматически делает их статическими. Поэтому нам не требуется ключевое слово static.
В Java статические члены обрабатываются не так, как члены-объекты. Это означает, что для статических членов нам недоступны такие вещи, как реализация интерфейса, помещение экземпляра в ассоциативный список (map) или передача его в качестве параметра методу, который принимает объект.
В Kotlin static не является ключевым словом и вместо статических членов используются объекты-компаньоны, позволяющие преодолеть вышеуказанные ограничения.
- В этом и заключается преимущество.
- Даже если члены объектов-компаньонов выглядят как статические члены в других языках, во время выполнения они все равно остаются членами экземпляров реальных объектов и могут, например, реализовывать интерфейсы.
В Java существует множество решений для асинхронной работы: RxJava, AsyncTask (уже официально не поддерживается), обработчики, обратные вызовы...
Наряду со всеми этими возможностями в Kotlin также имеются корутины (coroutines, также их называют сопрограммами), которые упрощают работу.
Корутины (или легковесные потоки) не являются отдельными потоками, но несколько корутин могут совместно использовать один поток.
7. Проверяемые исключения
Такие исключения, как IOException и FileNotFoundException, присутствуют в Java, но не поддерживаются в Kotlin.
- Причина в том, что они ничего не делают, кроме как содержат комментарий в блоке catch.
В Kotlin модификаторы lateinit и by Lazy позволяют инициализировать значения до их фактического использования.
val myUtil by lazy {
MyUtil(parameter1, parameter2)
}
lateinit var myUtil: MyUtil
Вышеприведенный код инициализирует объект MyUtil. Но это будет сделано только при первом использовании myUtil.
Оба варианта служат одной цели, но по факту сильно отличаются. Один является неизменяемым (val), другой — изменяемым (var).
@Injectlateinit var myUtil: MyUtil
- Ключевое слово lateinit было специально введено в Kotlin для переменных внедрения зависимостей (DI). Его следует использовать для изменяемых или устанавливаемых извне значений. Это полезно, если мы не хотим инициализировать значение, но при этом хотим избежать проверки на null.
if (foo::bar.isInitialized) {
println(foo.bar)
}
Переменная lateinit может быть инициализирована из любого места, откуда доступен объект.
В свою очередь, Java не поддерживает отложенную инициализацию, поэтому значения инициализируются, даже если они не используются.
Вот некоторые различия между этими двумя мощными языками.
Благодарю за внимание!
Сравниваем Java и Kotlin
Предлагаю начать с общих черт. Статическая типизация Бесплатны и с открытым кодом Код преобразуется в байт-код Интероперабельность Объектно-ориентированные языки программирования 1. Статическая...
habr.com