Migrando do Java para o Kotlin
1. Visão geral
Neste tutorial, vamos dar uma olhada em como podemos migrar de Java paraKotlin. Embora veremos muitos exemplos básicos, este artigo não é uma introdução ao Kotlin. Para um artigo dedicado, você pode começar comthis writeup here.
Aqui, veremos exemplos básicos de migração de nosso código Java para Kotlin, como instruções de impressão simples, definição de variáveis e gerenciamento de nulidade.
Em seguida, iremos para as áreas internas, como instruções de controle como if-else e instruções switch.
Finalmente, estamos passando para definir classes e trabalhar com coleções.
Leitura adicional:
Classes de dados em Kotlin
Um exemplo rápido e prático de uso de classes de dados no Kotlin.
Modificadores de visibilidade em Kotlin
Descubra os modificadores de visibilidade de Kotlin e veja como eles diferem daqueles encontrados em Java.
Guia Completo de Segurança Nula em Kotlin
Um guia rápido e prático para os recursos de segurança nulos incorporados na linguagem de programação Kotlin.
2. Migrações básicas
Vamos começar com exemplos simples de como migrar instruções simples.
2.1. Imprimir declarações
Para começar, vamos ver como funciona a impressão. Em Java:
System.out.print("Hello, example!");
System.out.println("Hello, example!");
Em Kotlin:
print("Hello, example!")
println("Hello, example!")
2.2. Definindo variáveis
Em Java:
final int a;
final int b = 21;
int c;
int d = 25;
d = 23;
c = 21;
Em Kotlin:
val a: Int
val b = 21
var c: Int
var d = 25
d = 23
c = 21
Como podemos ver, o ponto-e-vírgula no Kotlin é opcional. O Kotlin também utiliza inferência de tipo aprimorada e não precisamos definir tipos explicitamente.
Sempre que quisermos criar uma variável final, podemos simplesmente usar“val” em vez de“var”.
2.3. Fundição
Em Java, precisamos executar a conversão desnecessária em situações como:
if(str instanceof String){
String result = ((String) str).substring(1);
}
No Kotlin, a transmissão inteligente nos permite pular uma transmissão redundante:
if (str is String) {
val result = str.substring(1)
}
2.4. Operações de bit
As operações de bits no Kotlin são muito mais intuitivas.
Vamos ver isso em ação, com o Java:
int orResult = a | b;
int andResult = a & b;
int xorResult = a ^ b;
int rightShift = a >> 2;
int leftShift = a << 2;
E em Kotlin:
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. Null-Safety
Em Java:
final String name = null;
String text;
text = null;
if(text != null){
int length = text.length();
}
Portanto, não há restrição em Java para atribuir null a variáveis e usá-las. Ao usar qualquer variável, geralmente somos forçados a fazer uma verificação nula também.
Este não é o caso do Kotlin:
val name: String? = null
var lastName: String?
lastName = null
var firstName: String
firstName = null // Compilation error!!
Por padrão, Kotlin assume que os valores não podem sernull.
Não podemos atribuirnull à referênciafirstName, e se tentarmos, isso causará um erro do compilador. Se queremos criar uma referência nula, precisamos anexar o ponto de interrogação (?) À definição do tipo, como fizemos na primeira linha.
Mais sobre isso pode ser encontrado emthis article.
4. Operações de String
Strings funciona da mesma maneira que em Java. Podemos fazer operações semelhantes comoappende obter uma parte deString também.
Em 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";
Em Kotlin:
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()
Isso parecia bem fácil:
-
Podemos interpolarStrings usando o caractere“$”, e as expressões serão avaliadas em tempo de execução. Em Java, poderíamos conseguir algo semelhante usandoString.format()
-
Não há necessidade de quebrar seqüências de linhas múltiplas como em Java. O Kotlin oferece suporte imediato a eles. Só precisamos lembrar de usar aspas triplas
Não há símbolo para continuação de linha no Kotlin. Como sua gramática permite ter espaços entre quase todos os símbolos, podemos simplesmente quebrar a declaração:
val text = "This " + "is " + "a " +
"long " + "long " + "line"
No entanto, se a primeira linha da declaração for uma declaração válida, não funcionará:
val text = "This " + "is " + "a "
+ "long " + "long " + "line" // syntax error
Para evitar esses problemas ao quebrar declarações longas em várias linhas, podemos usar parênteses:
val text = ("This " + "is " + "a "
+ "long " + "long " + "line") // no syntax error
5. Loops e declarações de controle
Assim como qualquer outra linguagem de programação, também em Kotlin temos instruções de controle e loops para tarefas repetitivas.
5.1. For Loop
Em Java, temos vários tipos de loops para iterar em uma coleção ou umMap, como:
for (int i = 1; i < 11 ; i++) { }
for (int i = 1; i < 11 ; i+=2) { }
for (String item : collection) { }
for (Map.Entry entry: map.entrySet()) { }
Em Kotlin, temos algo semelhante, mas mais simples. Como já estamos familiarizados, a sintaxe de Kotlin tenta imitar a linguagem natural o máximo possível:
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 eWhen
Podemos usar instruçõesswitch em Java para tomar decisões seletivas:
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";
}
Em Kotlin, em vez de uma declaraçãoswitch, usamos uma declaraçãowhen para tomar decisões seletivas:
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" }
}
A declaraçãowhen pode atuar como uma expressão ou uma declaração, com ou sem um argumento:
val y = ... // some value
val yResult = when {
isNegative(y) -> "is Negative"
isZero(y) -> "is Zero"
isOdd(y) -> "is odd"
else -> "otherwise"
}
6. Aulas
Em Java, definimos uma classe de modelo e as acompanhamos com setters e getters padrão:
package com.example;
public class Person {
private long id;
private String name;
private String brand;
private long price;
// setters and getters
}
No Kotlin, getters e setters são gerados automaticamente:
package com.example
class Person {
var id: Long = 0
var name: String? = null
var brand: String? = null
var price: Long = 0
}
A modificação da visibilidade do getter / setter também pode ser alterada, mas tenha em mente que a visibilidade do getter deve ser igual à visibilidade da propriedade.
No Kotlin, todas as classes vêm com os seguintes métodos (podem ser substituídos):
-
toString (representação de string legível para um objeto)
-
hashCode (fornece um identificador exclusivo para um objeto)
-
equals (usado para comparar dois objetos da mesma classe para ver se eles são iguais)
7. Colecções
Bem, sabemos que Coleções é um conceito poderoso com qualquer linguagem de programação; Simplificando, podemos coletar objetos semelhantes e executar operações com eles. Vamos dar uma olhada naqueles em Java:
final List numbers = Arrays.asList(1, 2, 3);
final Map map = new HashMap();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");
// Java 9
final List numbers = List.of(1, 2, 3);
final Map map = Map.of(
1, "One",
2, "Two",
3, "Three");
Agora, no Kotlin, podemos ter coleções semelhantes:
val numbers = listOf(1, 2, 3)
val map = mapOf(
1 to "One",
2 to "Two",
3 to "Three")
A execução de operações também é interessante, como em Java:
for (int number : numbers) {
System.out.println(number);
}
for (int number : numbers) {
if(number > 5) {
System.out.println(number);
}
}
Em seguida, podemos executar as mesmas operações no Kotlin de uma maneira muito mais simples:
numbers.forEach {
println(it)
}
numbers
.filter { it > 5 }
.forEach { println(it) }
Vamos estudar um exemplo final sobre a coleta de números pares e ímpares emMap deString como chaves eList deIntegers como seus valores. Em Java, teremos que escrever:
final Map> 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);
}
Em Kotlin:
val groups = numbers.groupBy {
if (it and 1 == 0) "even" else "odd"
}
8. Conclusão
Este artigo serve como ajuda inicial ao passar do Java para o Kotlin.
Embora a comparação tenha sido apenas uma dica de como o Kotlin pode ser simples e intuitivo, outros artigoscan be found here.