Pílula K#08 — Tudo sobre Strings

Klaus Dellano
HavanLabs
Published in
7 min readDec 18, 2023

A pílula de hoje ajudará você a entender e desmistificar tudo sobre o controle das Strings no Kotlin! Então pega o café, o notepad++, e simbora!

As strings no Kotlin são imutáveis, assim como no Java. Isso significa que não é possível alterar uma string depois de criá-la. No entanto, podemos derivar uma nova string a partir de uma existente.

O Kotlin enriqueceu a classe String do Java com funcionalidades adicionais. Um exemplo rápido, para iniciarmos essa dose, seria o método padEnd() nos permite formatar uma string da seguinte forma:

“Hello”.padEnd(10, ‘!’)


// Saída
"Hello!!!!!"

Como acessar caracteres de uma String?

Para acessar os elementos (caracteres) de uma string, usamos o operador de acesso por índice. Por exemplo:

val minhaString = “Oi, pessoal!” 
val item = minhaString[1]

Aqui, a variável item contém o caractere “i”, que é o segundo caractere da string minhaString. Isso ocorre porque a indexação no Kotlin começa a partir de 0, não de 1.

val minhaString = "Oi, pessoal!" 
var item: Char
item = minhaString[0] // item contém 'O'
item = minhaString[9] // item contém 'a'

E claro, se não prestarmos atenção na string que estamos manipulando, podemos ocasionar o famoso erro: ‘StringIndexOutOfBoundsException’, que acontece quando fornecemos um índice fora dos limites permitidos para o acesso de caracteres individuais da string. Por exemplo:

val minhaString = "Oi, pessoal!" 
var item: Char

item = minhaString[12] // Erro! StringIndexOutOfBoundsException
item = minhaString[-1] // Erro! StringIndexOutOfBoundsException

Nesse caso, estamos tentando acessar o caractere que está na posição 12 da string. Dai você pode se perguntar: `Mas como assim mano? Minha string tem 12 letras, e quero acessar a última letra, que está na 12° posição!!!`. Mas depois tu lembra que as posições iniciam no índece 0 e não do 1. E esse erro é bem comum, então já vai se acostumando.

Uma das maneiras de consegueir o último caractere é utilizando o método last().

val minhaString = "Oi, pessoal!" 
var item: Char

item = minhaString.last() // item contém '!'

/*
last() nada mais é do que pegar o tamanho do conteúdo e subtrair 1:

fun String.last():
return this[this.length - 1]
}
*/

Iterar por uma String

Se você precisar iterar pelos elementos de uma string, pode fazer isso facilmente usando um loop for.

fun main() { 
val minhaString = "Oi!"
for (caractere in minhaString) {
println(caractere)
}
}

// Saída
"O"
"i"
"!"

Strings são Imutáveis

Assim como no Java, as strings são imutáveis no Kotlin. Isso significa que não é possível alterar caracteres individuais de uma string. Por exemplo:

var minhaString = “Oi!” 
minhaString[0] = ‘o’ // Erro!

No entanto, você pode atribuir novamente uma variável de string se você a declarou usando a palavra-chave var. (Pílula K #03)

String Templates

Uma das características incríveis do Kotlin são os String Templates (STs), literais de string que contêm expressões embutidas.

Por exemplo, em Java, teríamos que fazer algo assim:

String mensagem = "n = " + n;

Mas no Kotlin, é muito mais simples:

val mensagem = "n = $n"

Podemos usar qualquer expressão válida do Kotlin em um ST:

val mensagem = "n + 1 = ${n + 1}"

E não para por aí! Podemos até mesmo adicionar lógica neles:

val mensagem = "$n é ${if(n > 0) "positivo" else "não positivo"}"

Observe que dentro das chaves, temos uma expressão válida do Kotlin. Isso é possível porque, ao contrário do Java, muitas construções do Kotlin são expressões.

Os String Templates são resolvidos avaliando a expressão e invocando o método toString() no resultado da avaliação.

String Templates Aninhados

Os STs também podem ser aninhados. Podemos criar templates mais complexos, que incorporam outros templates:

val n = -3
val mensagem = "$n é ${if (n > 0) "positivo" else if (n < 0) "negativo e ${if (n % 2 == 0) "par" else "ímpar"}" else "zero"}"
print(mensagem)

//Saída
"-3 é negativo e ímpar"

O analisador de templates de string começa a resolvê-los a partir do template mais aninhado, avalia-o e invoca o método toString() nele.

"Bonitinho né? Mas…"

… só porque é possível aninhar, não significa que vai usar pra tudo e sempre… peloAmor neh?… tente manter os templates o mais simples possível, sua equipe agradece…

Escapando o Símbolo de Dólar

E se quisermos usar um símbolo de dólar cru e não como parte de um String Template? Podemos escapá-lo usando uma barra invertida antes dele:

val mensagem = "n = \$n"
print(message1)

//Saída
"n = $n"

O que vem depois do símbolo de dólar se torna uma string normal — ela não é mais avaliada e é interpretada como está.

String Literais no Kotlin

As strings são uma sequência de caracteres. Por exemplo, “Olá, HAVAN!” é uma string literal.

No Kotlin, todas as strings são objetos da classe String. Isso significa que as strings literais, como “Olá, HAVAN!”, são implementadas como instâncias dessa classe.

String Literals são uma parte indispensável da linguagem. Elas nos permitem trabalhar com texto e criar mensagens personalizadas. Vamos explorar as duas principais formas de declarar String Literais em Kotlin.

String Escapada

Uma String Escapada é uma sequência de caracteres que pode conter caracteres especiais. Esses caracteres especiais são precedidos por uma barra invertida (\) para indicar que eles têm um significado especial. Aqui está um exemplo de uma String Escapada:

val saudacao = "Olá, mundo!\nOlá, Havan!"
print(saudacao)

//Saída
"Olá, mundo!"
"Olá, Havan!"

Neste exemplo, a barra invertida seguida de “n” (\n) indica que queremos inserir uma nova linha na String. Outros caracteres especiais que podemos usar em uma String Escapada incluem:

  • \t — insere uma tabulação
  • \b — insere um backspace
  • \r — insere um retorno de carro
  • \’ — insere um caractere de aspas simples
  • \” — insere um caractere de aspas duplas
  • \\ — insere uma barra invertida
  • \$ — insere um símbolo de dólar

(fica o exercício pesquisar pra que serve cada uma :D)

String Multilinha (ou Raw String)

Uma String Multilinha, como o nome sugere, nos permite criar uma string que abrange várias linhas. Ela é delimitada por três aspas (“ “” “) e pode conter qualquer texto, incluindo quebras de linha. Aqui está um exemplo de uma String Multilinha:

val text = """
for (x in "abc")
print(x)
"""

Para remover o espaço em branco à esquerda das linhas, usamos da função trimMargin() .

val texto = """
|O Brasil
|Que queremos
|Só depende de nós
|(Luciano Hang)
""".trimMargin()

Por padrão, usamos o caractere pipe (|) como prefixo de margem, mas você pode escolher outro caractere e passá-lo como parâmetro, como trimMargin(“>”).

val texto = """
>O Brasil
>Que queremos
>Só depende de nós.
>(Luciano Hang)
""".trimMargin(">")

Tudo sobre o Dollar Sign

Para explicar melhor (na prática), vamos supor que estamos trabalhando com consultas ao MongoDB em nossa aplicação Kotlin. Além disso, queremos consultar a coleção de pessoas em busca daqueles que têm 18 anos ou mais:

db.pessoas.find(
{
"idade": { $gte: 18 }
}
)

Podemos perceber que nossa consulta é uma string multilinha com um símbolo de dólar no operador $gte. Vamos começar vendo se podemos armazenar essa consulta como está na raw string:

val encontrarAdultosQuery = """
db.pessoas.find(
{
"idade": { $gte: 18 }
}
)
"""

Infelizmente, recebemos um erro de compilação porque o Kotlin tenta interpolar $gte como uma variável Kotlin, que não está definida. Agora, vamos verificar se podemos escapar o símbolo de dólar:

val encontrarAdultosQuery = """
db.pessoas.find(
{
"idade": { \$gte: 18 }
}
)
"""

Infelizmente, não temos sorte novamente! Recebemos um erro de compilação porque o Kotlin não suporta a escape de caracteres especiais dentro da raw string. Então, como resolver esse problema ao usar o símbolo de dólar em uma string multilinha?

"Txan txan txan txaaamm"

Usando Interpolação de String com Literais

Se quisermos usar um símbolo de dólar em uma raw string, a melhor prática é usar ${‘$’}. Nessa abordagem, o Kotlin utiliza a interpolação de string usando ${} com o símbolo de dólar como um caractere literal (‘$’):

val encontrarAdultosQuery = """
db.pessoas.find(
{
"idade": { ${'$'}gte: 18 }
}
)
"""

//Saída
"""
db.pessoas.find(
{
"idade": { $gte: 18 }
}
)
"""

Fantástico! Parece que acertamos dessa vez. Além disso, devemos observar que essa abordagem também funciona para strings multilinhas com aspas duplas com os caracteres de quebra de linha (\n):


val encontrarAdultosQuery = "db.pessoas.find(\n {\n \"idade\": { ${'$'}gte: 18 }\n }\n)"
print(encontrarAdultosQuery)

//Saída
"""
db.pessoas.find(
{
"idade": { $gte: 18 }
}
)
"""

Propriedades e Funções mais usadas

Como os literais no Kotlin são implementados como instâncias da classe String, você pode usar vários métodos e propriedades dessa classe.

  • A propriedade ‘length’ retorna o comprimento da sequência de caracteres de uma string.
  • A função compareTo compara a String (objeto) com o objeto especificado. Retorna 0 se o objeto for igual ao objeto especificado.
  • A função ‘get’ retorna o caractere no índice especificado. Você pode usar o operador de acesso ao índice em vez da função get, pois o operador chama internamente a função get.
  • A função ‘plus’ retorna uma nova string obtida pela concatenação dessa string com a string passada para essa função. Você pode usar o operador + em vez da função plus, pois o operador + chama a função plus por baixo dos panos.
  • A função ‘subSequence’ retorna uma nova sequência de caracteres a partir do índice de início e do índice de término.
val s1 = "Iai, como vai?"
val s2 = "Iai, como vai?"
var resultado: String
println("O comprimento da string s1 é ${s1.length}.")

resultado = if (s1.compareTo(s2) == 0) "iguais" else "diferentes"
println("As strings s1 e s2 são $resultado.")

println("O terceiro caractere de s1 é '${s1.get(2)}'.")
println("E o quarto caractere de s1 é '${s1[3]}'.")

resultado = s1.plus(" Tudo bem?")
println("resultado = $resultado")
println("Substring é \"${s1.subSequence(5, 9)}\"")

//Saída
"O comprimento da string s1 é 14."
"As strings s1 e s2 são iguais."
"O terceiro caractere de s1 é 'i'."
"E o quarto caractere de s1 é ','."
"resultado = Iai, como vai? Tudo bem?"
"Substring é "como""

eeeeeeeeeeeeeeeeeeeeeeeeeeeeee…..

Amém senhor! Finalizamos…

É, tem pílulas que descem rasgando mesmo.

Vou deixar você absorver esse conteúdo… mas aconselho salvar em algum lugar pra revisar depois. Até a próxima.

--

--

Klaus Dellano
HavanLabs

Developer Engineer at HAVAN, focusing on Mobile and RFID.