Kotlin Cheat Sheet: דף עזר מהיר
עודכן לאחרונה
Hello World ויסודות
תוכנית Kotlin מתחילה בפונקציית main ברמה העליונה, בלי צורך במחלקה.
| תחביר | משמעות |
|---|---|
fun main() { println("Hello") } | נקודת הכניסה של תוכנית |
println("text") | הדפסת שורה לפלט הסטנדרטי |
print("text") | הדפסה בלי ירידת שורה בסוף |
// comment | הערה בשורה אחת |
/* comment */ | הערה מרובת שורות |
val input = readLine() | קריאת שורה מ-stdin (String? שיכול להיות null) |
val line = readln() | קריאת שורה מ-stdin (לא null, Kotlin 1.6+) |
משתנים (val / var) וטיפוסים
העדיפו val; השתמשו ב-var רק כשהערך חייב להשתנות.
| תחביר | משמעות |
|---|---|
val name = "Ada" | משתנה לקריאה בלבד, הטיפוס מוסק כ-String |
var count = 0 | משתנה שניתן לשינוי |
val age: Int = 30 | ציון טיפוס מפורש |
Int, Long, Double, Float | טיפוסים מספריים (42, 42L, 3.14, 3.14f) |
Boolean, Char, String | true/false, 'a', "text" |
val big = 1_000_000 | קווים תחתונים לליטרלים קריאים |
"3".toInt(), "2.5".toDouble() | המרת מחרוזת למספר |
42.toString() | מספר למחרוזת |
const val MAX = 10 | קבוע בזמן קומפילציה (ברמה העליונה או בתוך object) |
מחרוזות ו-templates
String templates מחליפים שרשור כמעט בכל מקום.
| תחביר | משמעות |
|---|---|
"Hi, $name" | הכנסת משתנה למחרוזת |
"Total: ${price * qty}" | הכנסת ביטוי |
s.length | מספר התווים |
s.uppercase(), s.lowercase() | שינוי אותיות גדולות/קטנות |
s.trim() | הסרת רווחים בהתחלה ובסוף |
s.contains("x"), s.startsWith("a") | חיפוש בתוך מחרוזת |
s.substring(0, 3) | חיתוך לפי טווח אינדקסים |
s.split(",") | פיצול ל-List<String> |
s[0] | התו באינדקס מסוים |
"""raw text""" | מחרוזת גולמית מרובת שורות, בלי escaping |
"%.2f".format(3.14159) | פלט מעוצב (3.14) |
Null safety
טיפוס אינו יכול להיות null כברירת מחדל; הוסיפו ? כדי לאפשר null, והקומפיילר יחייב אתכם לטפל בזה.
| תחביר | משמעות |
|---|---|
var s: String? = null | טיפוס שיכול להיות null |
s?.length | קריאה בטוחה: מחזירה null אם s הוא null |
s?.length ?: 0 | אופרטור Elvis: ערך חלופי כשיש null |
s!!.length | הצהרה שהערך אינו null: זורקת שגיאה אם s הוא null |
if (s != null) s.length | Smart cast לטיפוס שאינו null בתוך הבדיקה |
s?.let { println(it) } | הרצת בלוק רק כשהערך אינו null |
val n = s?.toIntOrNull() | המרה, או null בקלט שגוי |
lateinit var x: String | var שאינו null ומאותחל מאוחר יותר |
אופרטורים
| אופרטור | משמעות |
|---|---|
+ - * / % | אריתמטיקה (/ על Int הוא חילוק שלמים) |
+= -= *= /= %= | השמה מורחבת |
++ -- | הגדלה / הקטנה ב-1 |
== != | שוויון מבני (קורא ל-equals) |
=== !== | שוויון הפניות (אותו אובייקט) |
< > <= >= | השוואה |
&& || ! | וגם / או / לא לוגיים |
a in 1..10 | שייכות לטווח או לאוסף |
x as Int, x as? Int | המרה / המרה בטוחה (null בכישלון) |
x is String | בדיקת טיפוס (עם smart cast בהצלחה) |
בקרת זרימה (if / when)
if ו-when הם ביטויים: הם מחזירים ערך.
| תחביר | משמעות |
|---|---|
if (a > b) x else y | if כביטוי (אין ב-Kotlin אופרטור טרינרי ?:) |
if (c) { ... } else if (d) { ... } else { ... } | ענפים משורשרים |
when (x) { 1 -> "one"; 2 -> "two"; else -> "other" } | התאמת ערך |
when (x) { 1, 2 -> "low" } | כמה ערכים בענף אחד |
when (x) { in 1..9 -> "digit" } | התאמת טווח |
when (x) { is String -> x.length } | התאמת טיפוס (עם smart cast) |
when { x < 0 -> "neg"; x == 0 -> "zero"; else -> "pos" } | when בלי נושא, כמו if/else if |
val label = when (x) { ... } | when כביטוי (דורש else) |
לולאות וטווחים
| תחביר | משמעות |
|---|---|
for (i in 1..5) | טווח כולל מ-1 עד 5 |
for (i in 1 until 5) | מ-1 עד 4 (הסוף לא כלול) |
for (i in 0..<5) | אותו דבר, בתחביר טווח פתוח (Kotlin 1.9+) |
for (i in 10 downTo 1 step 2) | ספירה לאחור בקפיצות |
for (item in list) | מעבר על אוסף |
for ((i, item) in list.withIndex()) | אינדקס ואיבר יחד |
for (ch in "abc") | מעבר על התווים של מחרוזת |
while (cond) { ... } | לולאה כל עוד התנאי מתקיים |
do { ... } while (cond) | רץ לפחות פעם אחת |
break, continue | יציאה מהלולאה / דילוג לאיטרציה הבאה |
repeat(3) { println(it) } | הרצת בלוק n פעמים |
פונקציות
| תחביר | משמעות |
|---|---|
fun add(a: Int, b: Int): Int { return a + b } | הצהרה על פונקציה |
fun add(a: Int, b: Int) = a + b | פונקציה של ביטוי יחיד, טיפוס ההחזרה מוסק |
fun greet(name: String = "world") | ערך ברירת מחדל לפרמטר |
greet(name = "Ada") | ארגומנט בשם |
fun log(vararg items: String) | מספר משתנה של ארגומנטים |
fun say(): Unit | ללא ערך החזרה (Unit אופציונלי) |
val square = { x: Int -> x * x } | Lambda שנשמרת במשתנה |
fun String.shout() = uppercase() + "!" | פונקציית הרחבה (Extension) |
fun apply(f: (Int) -> Int) = f(2) | פונקציה כפרמטר |
list.map { it * 2 } | Lambda בסוף הקריאה, it הוא הפרמטר היחיד |
רשימות
listOf היא לקריאה בלבד; mutableListOf ניתנת לשינוי.
| תחביר | משמעות |
|---|---|
val nums = listOf(1, 2, 3) | רשימה לקריאה בלבד |
val items = mutableListOf("a") | רשימה שניתנת לשינוי |
nums[0], nums.first(), nums.last() | גישה לאיברים |
nums.getOrNull(9) | גישה בטוחה, null אם מחוץ לטווח |
items.add("b"), items.remove("a") | הוספה / הסרה |
items[0] = "z" | החלפה לפי אינדקס |
nums.size, nums.isEmpty() | גודל ובדיקת ריקות |
x in nums, nums.contains(x) | שייכות |
nums.indexOf(2) | המיקום של איבר, -1 אם הוא לא קיים |
nums.subList(0, 2) | חיתוך (הסוף לא כלול) |
nums.take(2), nums.drop(1) | n הראשונים / הכול חוץ מ-n הראשונים |
nums.sorted(), nums.reversed() | רשימה חדשה ממוינת / הפוכה |
nums.sum(), nums.average(), nums.maxOrNull() | צבירות |
nums.joinToString(", ") | חיבור למחרוזת אחת |
Pair(1, "a"), 1 to "a", Triple(1, 2, 3) | tuples קטנים בגודל קבוע |
Maps ו-sets
| תחביר | משמעות |
|---|---|
val m = mapOf("a" to 1, "b" to 2) | Map לקריאה בלבד |
val mm = mutableMapOf<String, Int>() | Map שניתנת לשינוי |
m["a"] | חיפוש (null אם חסר) |
m.getOrDefault("z", 0) | חיפוש עם ערך חלופי |
mm["c"] = 3 | הכנסה או עדכון |
for ((k, v) in m) | מעבר על הרשומות עם destructuring |
m.keys, m.values | אוספי המפתחות / הערכים |
"a" in m | שייכות של מפתח |
val s = setOf(1, 2, 2) | Set של ערכים ייחודיים ({1, 2}) |
mutableSetOf<Int>() | Set שניתן לשינוי |
פעולות על collections (lambdas)
| תחביר | משמעות |
|---|---|
list.map { it * 2 } | שינוי כל איבר |
list.filter { it > 2 } | שמירת איברים תואמים |
list.forEach { println(it) } | ביצוע פעולה על כל איבר |
list.any { it > 2 }, list.all { it > 0 } | האם איבר כלשהו / כל האיברים תואמים |
list.count { it % 2 == 0 } | ספירת התאמות |
list.find { it > 2 } | ההתאמה הראשונה או null |
list.sortedBy { it.length } | מיון לפי מפתח |
list.groupBy { it.first() } | קיבוץ ל-Map |
list.distinct() | הסרת כפילויות |
list.fold(0) { acc, x -> acc + x } | צמצום עם ערך התחלתי |
list.zip(other) | צימוד שתי רשימות לזוגות |
list.flatMap { it.toList() } | מיפוי ואז שיטוח |
מחלקות ו-data classes
| תחביר | משמעות |
|---|---|
class User(val name: String, var age: Int) | מחלקה עם בנאי ראשי ומאפיינים |
val u = User("Ada", 36) | יצירת מופע (בלי new) |
u.name, u.age = 37 | קריאה / כתיבה של מאפיינים |
data class Point(val x: Int, val y: Int) | equals, hashCode, toString, copy בחינם |
p.copy(y = 5) | העתקה עם שינוי של חלק מהמאפיינים |
val (x, y) = p | הצהרת destructuring |
open class Base, class Sub : Base() | ירושה (מחלקות הן final כברירת מחדל) |
override fun toString() = "..." | דריסת איבר |
object Config { val debug = true } | Singleton |
companion object { fun create() = User("", 0) } | איברים דמויי static |
enum class Color { RED, GREEN } | Enum |
sealed class Result | היררכיית מחלקות מוגבלת, ממצה ב-when |
interface Shape { fun area(): Double } | ממשק |
טיפול בשגיאות
| תחביר | משמעות |
|---|---|
try { ... } catch (e: Exception) { ... } | תפיסת exception |
try { ... } finally { ... } | הרצת ניקוי תמיד |
val n = try { s.toInt() } catch (e: NumberFormatException) { 0 } | try כביטוי |
throw IllegalArgumentException("bad") | זריקת exception |
require(x > 0) { "x must be positive" } | בדיקת ארגומנט (זורקת IllegalArgumentException) |
check(ready) { "not ready" } | בדיקת מצב (זורקת IllegalStateException) |
s.toIntOrNull() | מחזירה null במקום לזרוק |
runCatching { risky() }.getOrDefault(0) | עטיפת קריאה ב-Result |
Scope functions
חמש פונקציות עזר קטנות לעבודה עם אובייקט בתוך בלוק.
| תחביר | משמעות |
|---|---|
x.let { it + 1 } | it הוא האובייקט, מחזירה את תוצאת הבלוק |
x.run { this + 1 } | this הוא האובייקט, מחזירה את תוצאת הבלוק |
x.apply { field = 1 } | this הוא האובייקט, מחזירה את האובייקט |
x.also { println(it) } | it הוא האובייקט, מחזירה את האובייקט |
with(x) { field } | לא פונקציית הרחבה; this הוא x, מחזירה את תוצאת הבלוק |
x?.let { ... } | הדרך האידיומטית לבדוק null ולהשתמש בערך |
כל פיסת תחביר של Kotlin שצריך, בעמוד אחד. ה-Kotlin cheat sheet הזה הוא דף עזר מהיר לשפה שמאחורי Android וחלק גדול מה-JVM המודרני: הצהרה על משתנים, טיפול בטוח ב-null, הסתעפות עם when, לולאות על טווחים, כתיבת פונקציות ועבודה עם רשימות ו-maps.
כל מה שכאן הוא Kotlin סטנדרטי ורץ באותה צורה על ה-JVM, על Android ועל Kotlin Multiplatform. העתיקו את מה שצריך, או נסו בזמן אמת בעורך האונליין של Kotlin: הדביקו קטע קוד, לחצו Run וראו את הפלט בדפדפן.
שאלות נפוצות על ה-Kotlin cheat sheet
האם ה-Kotlin cheat sheet הזה בחינם?
when, אופרטור של null safety או מתודה של collection.מה ההבדל בין val ל-var ב-Kotlin?
val מצהיר על הפניה לקריאה בלבד: משימים לה ערך פעם אחת ואי אפשר להשים מחדש. var מצהיר על משתנה שניתן להשים לו מחדש. שימו לב ש-val מקבע רק את ההפניה: ל-val list = mutableListOf(1) עדיין אפשר להוסיף איברים. הסגנון המקובל ב-Kotlin הוא להשתמש ב-val בכל מקום ולעבור ל-var רק כשבאמת צריך השמה מחדש.איך null safety עובד ב-Kotlin?
String לעולם לא יחזיק null; String? כן יכול. הקומפיילר לא יאפשר לקרוא למתודה על ערך שיכול להיות null בלי לטפל במקרה של null: עם קריאה בטוחה (s?.length), עם ערך חלופי של Elvis (s?.length ?: 0), עם בדיקת null שמבצעת smart cast (if (s != null)), או כמוצא אחרון עם הצהרת ה-not-null s!!, שזורקת NullPointerException אם הערך הוא בפועל null.מתי כדאי להשתמש ב-when במקום ב-if ב-Kotlin?
when בכל פעם שמשווים ערך אחד מול כמה אפשרויות: קבועים, טווחים, טיפוסים או שילוב שלהם, והשתמשו ב-if/else לתנאי יחיד של כן או לא. שניהם ביטויים, כך ש-val label = when (x) { ... } וגם val label = if (c) a else b אידיומטיים. when שמשמש כביטוי חייב להיות ממצה, ובדרך כלל זה אומר להוסיף ענף else (sealed classes ו-enums יכולים להיות ממצים גם בלעדיו).אפשר לתרגל Kotlin אונליין?
when, לולאות, פונקציות ו-collections, ובסוף מעניק תעודה בחינם.