π μ½νλ¦°(Kotlin)μ΄λ?

μ½νλ¦°μ JetBrainsμμ 2011λ μ 곡κ°ν μ μ νμ μ€νμμ€ νλ‘κ·Έλλ° μΈμ΄μ΄λ€.
- Javaμμ νΈνμ± : JVM μμμ λμνλ©° Javaμ 100% νΈνλλ€. κΈ°μ‘΄ Java νλ‘μ νΈμ μ½νλ¦°μ λ°λ‘ λμ νκ±°λ, Java λΌμ΄λΈλ¬λ¦¬λ₯Ό κ·Έλλ‘ κ°μ Έμ μ¬μ©ν μ μλ€.
- κ°κ²°ν μ½λ : Javaμ μ₯ν©ν μ½λ(보μΌλ¬νλ μ΄νΈ)λ₯Ό λν μ€μ¬, μ μ μ½λλ‘ λμΌν κΈ°λ₯μ ꡬννμ¬ μμ°μ±μ λμΈλ€.
- μμ μ± (Null Safety) : NPEλ₯Ό μ»΄νμΌ μμ μ λ°©μ§νμ¬ μμ μ μΈ κ°λ°μ΄ κ°λ₯
- λ€μν νμ©μ± : μλλ‘μ΄λ μ± κ°λ°, λ°±μλ μλ² κ°λ°(Spring λ±), λ©ν°νλ«νΌ κ°λ°μ νμ©
π λ³μ
μ½νλ¦°μ λ³μ μ μΈ μ κ°λ³ μ¬λΆ(var / val)λ₯Ό λͺ νν νμν΄μ£Όμ΄μΌ νλ€.
fun main() {
val num1 = 10L
var num2 = 20L
}
- val (Value) : λΆλ³ λ³μλ‘ μ΄κΈ°ν ν κ° λ³κ²½μ΄ λΆκ°λ₯νλ€. (μλ°μ final)
- var (Variable) : κ°λ³ λ³μλ‘ μ΄κΈ°ν ν κ° λ³κ²½μ΄ κ°λ₯νλ€.
π‘ Tip : λͺ¨λ λ³μλ μ°μ valλ‘ μ μΈνκ³ κΌ νμν κ²½μ°μλ§ varλ‘ λ³κ²½νλ κ²μ΄ ν΄λ¦° μ½λ μ μ§μ μ 리νλ€.
β νμ μΆλ‘ κ³Ό λͺ μμ νμ
μ½νλ¦°μ μλ°μ λ€λ₯΄κ² νμ μ μ§μ ν΄μ£Όμ§ μμλ μ»΄νμΌ μμ μ μΆλ‘ νλ€. νμ μ λͺ μνκ³ μΆλ€λ©΄ λ³μ λ€μ :νμ μ λΆμ¬μ€λ€.
fun main() {
val num1 = 10L // LongμΌλ‘ μΆλ‘
val num2: Long = 10L // λͺ
μμ νμ
μ μΈ
}
λ§μ½ λ³μλ₯Ό μ μΈκ³Ό λμμ μ΄κΈ°ννμ§ μλλ€λ©΄ νμ μΆλ‘ μ΄ λΆκ°λ₯νλ€. μ΄λ° κ²½μ°μλ νμ μ λͺ μν΄μ£Όμ΄μΌ νλ€.
fun main() {
val num1 // This variable must either have an explicit type or be initialized.
val num2: Long
}
μ΄κΈ°νλμ§ μμ λ³μλ μ¬μ©ν μ μλ€.
fun main() {
val num1: Long
println(num1) // Variable 'num1' must be initialized.
}
β κΈ°λ³Έ νμ
μλ°μλ reference type(ex. Long)κ³Ό primitive type(ex. long)μ΄ μλ€. reference typeμ μ¬μ©νμ¬ μ°μ°νλ κ²½μ° boxing, unboxingμ΄ μΌμ΄λλ©΄μ λΆνμν κ°μ²΄ μμ±μ΄ λ°μνλ€. κ·Έλ¬λ μ½νλ¦°μλ reference typeκ³Ό primitive typeμ ꡬλΆμ΄ μλ€. μ½νλ¦°μμλ μ€ν μμ μ boxing, unboxingμ κ³ λ €νμ§ μμλ λλλ‘ κ°μ₯ ν¨μ¨μ μΈ λ°©μμΌλ‘ μν©μ λ°λΌ μ²λ¦¬νλ€.
fun main() {
// 1. Primitive νμ
μΌλ‘ λ³νλλ κ²½μ° (μ΅μ ν)
val a: Long = 100L
val b: Long = 200L
val sum = a + b // μλ°μ long + long μ°μ°κ³Ό λμΌνκ² λμ
// 2. Reference νμ
(Wrapper)μ΄ λΆκ°νΌν κ²½μ°
val nullableSum: Long? = sum // null νμ© μ μλ°μ Long κ°μ²΄λ‘ μμ±
}
π Null Safety : μ½νλ¦°μ ν΅μ¬
μ½νλ¦°μ κ°μ₯ ν° νΉμ§μ Nullableκ³Ό Non-nullable νμ μ μ격ν ꡬλΆνλ€λ μ μ΄λ€. μ½νλ¦°μμλ κΈ°λ³Έμ μΌλ‘ λͺ¨λ λ³μλ nullμ΄ λ€μ΄κ° μ μλ€. λ§μ½ nullμ΄ λ€μ΄μ¬ μ μλ λ³μλΌλ©΄ μ μΈ μ nullable νμλ₯Ό ν΄μ£Όμ΄μΌ νλ€.
fun main() {
val num: Long? = 1_000L
}
β οΈ μ£Όμν μ μ½νλ¦°μ΄ μμμ μ΅μ νν΄μ£Όμ§λ§, Nullable(?) νμ μ λ¨μ©νλ©΄ μλ°μ λ§μ°¬κ°μ§λ‘ λ΄λΆμ μΌλ‘ Boxingμ΄ λ°μνμ¬ μ±λ₯ μ νκ° μκΈΈ μ μλ€. μ±λ₯μ΄ μ€μν 루νλ¬Έ λ±μμλ μ΅λν non-nullable νμ μ μ¬μ©νλ κ²μ΄ μ’λ€.
β Safe Callκ³Ό Elvis μ°μ°μ
λ³λλ‘ null 체ν¬λ₯Ό νμ§ μλλ€λ©΄ nullable μΈμμ κ²½μ° λ°λ‘ ν¨μλ₯Ό νΈμΆν μ μμΌλ―λ‘ Safe Call λλ Elvis μ°μ°μλ₯Ό μ¬μ©ν΄μΌ νλ€.
- Safe Call(?.) : nullμ΄ μλ λλ§ μ€ννκ³ , nullμ΄λ©΄ μ 체 κ²°κ³Όκ° nullμ΄ λλ€.
val str: String? = "ABC"
println(str?.length)
- Elvis μ°μ°μ(?:) : μμ μ°μ° κ²°κ³Όκ° nullμ΄λ©΄ λ€μ μ§μ ν κΈ°λ³Έκ°μ μ¬μ©νλ€.
val str: String? = "ABC"
str?.length ?: 0
β null μλ λ¨μΈ(!!)
μ λ§ nullμ΄ μλμ΄ νμ€ν λλ§ μ¬μ©νλ€. λ§μ½ nullμΌ κ²½μ° λ°νμμ NPEκ° λ°μνλ―λ‘ μ£Όμν΄μΌνλ€.
fun ignoreNull(str: String?): Boolean {
return str!!.startsWith("A")
}
β νλ«νΌ νμ
μλ° μ½λμμ @Nullableμ΄λ @NotNull μ΄λ Έν μ΄μ μ΄ μμ΄ μ½νλ¦°μ΄ null κ°λ₯μ±μ μ μ μλ νμ μΌλ‘,
μλ°μ μ½νλ¦°μ ν¨κ» μ¬μ©ν λ κ°μ₯ μ£Όμν΄μΌ νλ λΆλΆμ΄λ€. μ½νλ¦°μμ Non-nullableλ‘ κ°μ£Όνλ€κ° λ°νμμ
NPEκ° λ°μν μ μλ€. μλ° λΌμ΄λΈλ¬λ¦¬ μ¬μ© μ λ°λμ λΌμ΄λΈλ¬λ¦¬ λ΄λΆλ₯Ό νμΈνκ³ λ κ°λ₯μ±μ μ²λ¦¬ν΄μΌ νλ€.
π νμ
1. κΈ°λ³Έ νμ
- Byte
- Short
- Int
- Long
- Double
- Float
- λΆνΈ μλ μ μλ€
μ½νλ¦°μμλ μ μΈλ κΈ°λ³Έκ°μ λ³΄κ³ νμ μ μΆλ‘ νλ€.
val num1 = 3 // Int
val num2 = 3L // Long
val num3 = 3.0f // Float
val num4 = 3.0 // Double
κΈ°λ³Έ νμ λ³ν
μ½νλ¦°μ μλ°μ λ¬λ¦¬ κΈ°λ³Έ νμ κ°μ μμμ νλ³νμ νμ©νμ§ μλλ€.
val num1 = 4
// val num2: Long = num2 // Type mismatch
val num3: Long = num1.toLong() // λͺ
μμ νλ³ν
λ³μκ° nullableμ΄λΌλ©΄ μ μ ν μ²λ¦¬κ° νμνλ€.
val num1: Int? = 3
val num2: Long = num1?.toLong() ?: 0L
2. νμ μΊμ€ν
μλ°μ instanceofλ μ½νλ¦°μμ isλ‘ μ¬μ©λλ€. isλ‘ νμ μ νμΈνλ©΄ μ€λ§νΈ μΊμ€νΈκ° μΌμ΄λλ―λ‘ λ³λμ νλ³ν μ½λκ° νμ μλ€.
fun printNameIfPerson(obj: Any){
if (obj is Person) {
// objλ Person νμ
μΌλ‘ κ°μ£Όλ¨ (μ€λ§νΈ μΊμ€νΈ)
println(person.name)
}
}
- instanceof → is
- !(instanceof) -> !is
- (Person) obj -> obj as Person
nullable λ³μμ λνμ¬ νμ μΊμ€ν μ, NPEλ₯Ό λ°©μ§νλ €λ©΄ as?λ₯Ό λΆμ¬μΌ νλ€.
fun main() {
printNameIfPerson(null)
}
fun printNameIfPerson(obj: Any?) {
val person = obj as? Person // nullμ΄ μλλ©΄ νλ³ν, nullμ΄λ©΄ null λ°ν
println(person?.name)
}
3. μ½νλ¦°μ 3κ°μ§ νΉμ΄ν νμ
- Any
- μλ°μ Object. λͺ¨λ κ°μ²΄μ μ΅μμ νμ (Primitive Type ν¬ν¨)
- Any μ체λ‘λ nullμ ν¬ν¨ν μ μμ (Any? μ¬μ©ν΄μΌν¨)
- equals, hashCode, toString μ‘΄μ¬
- Unit
- μλ°μ voidμ λμΌν μν
- voidμ λ€λ₯΄κ² Unitμ κ·Έ μμ²΄λ‘ νμ μΈμλ‘ μ¬μ© κ°λ₯νλ€
- ν¨μν νλ‘κ·Έλλ°μμ Unitμ λ¨ νλμ μΈμ€ν΄μ€λ§ κ°λ νμ μ μλ―Έ. μ¦, μ½νλ¦°μ Unitμ μ€μ μ‘΄μ¬νλ νμ μ΄λΌλ κ²μ νν
- Nothing
- ν¨μκ° μ μμ μΌλ‘ μ’ λ£λμ§ μμμ λνλΈλ€. (무ν 루ν, 무쑰건 μμΈ λ°μ)
- μ€λ¬΄μμ μ μ°μ΄μ§λ μμ
4. String
μ½νλ¦°μ μλ°μ λ¬λ¦¬ λ¬Έμμ΄ μμμ λ³μλ₯Ό λ°λ‘ μ¬μ©ν μ μμ΄ κ°λ μ±μ΄ λ°μ΄λλ€.
val person = Person("μμ", 100);
val str = "μ¬λμ μ΄λ¦μ ${person.name}μ΄κ³ , λμ΄λ ${person.age}μΈ μ
λλ€."
val name = "μμ"
println("μ΄λ¦: $name") // μ€κ΄νΈ μλ΅ κ°λ₯
β Tip : μ€κ΄νΈλ μλ΅μ΄ κ°λ₯νμ§λ§ μλ΅νμ§ μλ κ²μ΄ κ°λ μ±, μΌκ΄ λ³ν, μ κ·μ νμ© μΈ‘λ©΄μμ μ’λ€.
μ¬λ¬ μ€μ κ±ΈμΉ λ¬Έμμ΄μ μμ±ν΄μΌ ν λ
"""
μ΄μ©κ΅¬μ μ©κ΅¬..
${name}
""".trimIndent() // μΈλ΄νΈ μ κ±°
λ¬Έμμ΄μ νΉμ λ¬Έμ κ°μ Έμ€κΈ°
val str = "ABC"
println(str[0])
π μ°μ°μ
λλΆλΆμ μ°μ μ°μ°μ, λ Όλ¦¬ μ°μ°μ λ±μ μλ°μ λμΌνμ§λ§, λͺκ°μ§ μ°¨μ΄μ μ΄ μλ€.
β λλ±μ±, λμΌμ±
- == : λλ±μ±(κ°μ΄ κ°μμ§) λΉκ΅. λ΄λΆμ μΌλ‘ equals() νΈμΆ (μλ°μ equals)
- === : λμΌμ± λΉκ΅. μ£Όμκ°μ λΉκ΅νλ€. (μλ°μ ==)
β μ½νλ¦°μ μλ νΉμ΄ν μ°μ°μ
- in / !in : 컬λ μ μ΄λ λ²μμ ν¬ν¨λλμ§ νμΈ
- a..b : aλΆν° bκΉμ§μ λ²μ κ°μ²΄λ₯Ό μμ±νλ€.
- a[i] : aμμ νΉμ μΈλ±μ€ iλ‘ κ°μ κ°μ Έμ¨λ€.
- a[i] = b : aμ νΉμ μΈλ±μ€ iμ bλ₯Ό λ£λλ€.
β μ°μ°μ μ€λ²λ‘λ©
μ½νλ¦°μμλ κ°μ²΄λ§λ€ μ°μ°μλ₯Ό μ§μ μ μν μ μλ€.
fun main() {
val money1 = Money(1_000L)
val money2 = Money(2_000L)
println(money1 + money2) // μ°μ°μ μ€λ²λ‘λ©
}
data class Money(
val amount: Long
) {
operator fun plus(other: Money): Money {
return Money(this.amount + other.amount)
}
}