val name = "Alice"
Variable inmutable (inferida)
var age = 30
Variable mutable
val PI: Double = 3.14
Variable con tipo explícito
const val VERSION = "1.0"
Constante de compilación (top-level/object)
Int Long Float Double Boolean Char String
Tipos integrados
val msg = "Hello, $name!"
Plantilla de string
val sum = "Sum: ${a + b}" Plantilla con expresión
val text = """Multi-line string"""
String multilínea raw
if (x > 0) { ... } else if (x == 0) { ... } else { ... } If/else
val result = if (a > b) a else b
If como expresión
for (i in 1..10) { ... } For con rango
for (i in 1..10 step 2) { ... } Rango con step
for (i in 10 downTo 1) { ... } Rango descendente
for (item in list) { ... } Bucle for-in
list.forEach { println(it) } forEach con it implícito
when (x) {
1 -> ...
in 2..5 -> ...
else -> ...
} Expresión when (switch)
val name: String? = null
Tipo nullable
name?.length
Operador safe call
name ?: "unknown"
Operador Elvis (default si null)
name!!
Aserción no-null (lanza si null)
name?.let { println(it) } Ejecutar bloque si no es null
val len = name?.length ?: 0
Safe call + elvis
fun add(a: Int, b: Int): Int = a + b
Función de una expresión
fun greet(name: String) {
println("Hi $name")
} Función con bloque
fun greet(name: String = "World") {} Parámetro por defecto
greet(name = "Alice")
Llamada con argumento nombrado
fun sum(vararg nums: Int): Int = nums.sum()
Varargs
val multiply = { a: Int, b: Int -> a * b } Expresión lambda
fun String.shout() = this.uppercase()
Función de extensión
inline fun <T> measure(block: () -> T): T = block()
Higher-order inline
class User(val name: String, var age: Int)
Constructor primario
data class User(val id: Int, val name: String)
Data class (equals/hash/toString)
val (id, name) = user
Desestructurar data class
class User {
init { println("created") }
} Bloque init
open class Animal class Dog : Animal()
Herencia (requiere open)
interface Clickable { fun click() } Interfaz
sealed class Result
Sealed class (jerarquía restringida)
enum class Color { RED, GREEN, BLUE } Clase enum
object Singleton { val config = ... } Declaración object (singleton)
companion object { fun create() = ... } Companion object (estático)
val list = listOf(1, 2, 3)
Lista inmutable
val list = mutableListOf(1, 2, 3)
Lista mutable
val map = mapOf("a" to 1, "b" to 2) Map inmutable
val set = setOf(1, 2, 3)
Set inmutable
list.filter { it > 2 } Filtrar colección
list.map { it * 2 } Transformar cada elemento
list.fold(0) { acc, x -> acc + x } Fold (reduce con inicial)
list.groupBy { it % 2 } Agrupar por predicado
list.sortedBy { it.name } Ordenar por clave
list.firstOrNull { it > 10 } Primera coincidencia o null
suspend fun fetch(): String { ... } Función suspending
runBlocking { val x = fetch() } Ejecutar coroutine (bloqueante)
launch { doWork() } Coroutine fire-and-forget
val result = async { fetch() }.await() Async con resultado
delay(1000)
Delay no bloqueante (ms)
withContext(Dispatchers.IO) { file.read() } Cambiar dispatcher
coroutineScope { launch {...}; launch {...} } Scope de concurrencia estructurada
Cheat Sheet de Kotlin — Coroutines, Null Safety, Data Classes y Extensions
Kotlin salió de JetBrains en 2011 como alternativa menos verbosa a Java sobre la JVM, y Google lo adoptó como lenguaje preferido en Android en 2019; desde entonces ha crecido hasta cubrir null safety, corrutinas, data classes, jerarquías selladas y extensiones, manteniéndose como capa fina sobre el bytecode subyacente. La chuleta de abajo cubre más de 55 fragmentos entre básicos, null safety, funciones, clases, colecciones y corrutinas. La mayoría de los líos en código real no vienen de olvidar la sintaxis. Vienen de rarezas que parecen normales pero muerden. El operador `!!` transforma un nullable en no-nulo al precio de una `NullPointerException` si el valor era nulo de verdad. Un `lateinit var` solo admite tipos de referencia no-nulos y lanza `UninitializedPropertyAccessException` si se lee antes de tiempo. Un `when` sobre una clase sellada es exhaustivo solo cuando se asigna o retorna; usado como sentencia, el compilador deja pasar casos en silencio. Estos son los fragmentos que se acaban consultando al depurar precisamente eso: la cadena de safe calls, el destructuring de data class, el scope de corrutinas.
Trampas habituales en Kotlin
Hay un puñado de patrones que merecen estar en la primera pantalla de cualquier archivo Kotlin. `val` es el valor por defecto y `var` la excepción, porque el estado local rara vez necesita mutar y la inmutabilidad elimina una clase de bug de concurrencia sin esfuerzo. El operador Elvis `name ?: "unknown"` encadena naturalmente tras un safe call para producir un resultado no-nulo sin escalera de `if (x == null)`. `data class` genera `equals`, `hashCode`, `toString` y `copy` para que los tipos del dominio dejen de cargar con boilerplate, y el destructuring `val (id, name) = user` sale gratis. Las corrutinas deben vivir dentro de un `coroutineScope` o `viewModelScope`, no en `GlobalScope`, porque la concurrencia estructurada cancela hijos cuando muere el padre; `GlobalScope` filtra. Y `Unit` es un tipo real que devuelven las funciones sin retorno explícito, no la ausencia de uno, detalle que importa al guardar una referencia de función en un contenedor genérico. La chuleta agrupa todo esto en básicos, null safety, funciones, clases, colecciones y corrutinas, así la sección correcta queda a un clic.
- Más de 55 fragmentos prácticos
- 6 categorías desde básicos a coroutines
- Null safety y safe-call
- Data classes, sealed classes, objects
- Coroutines y concurrencia estructurada
- Copia al portapapeles con un clic
Gratis. Sin registro. Tus datos permanecen en tu navegador. Anuncios mediante Google AdSense (con consentimiento).
Por Marco B. ·