Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

임도현의 성장

[Kotlin] 코틀린 기본 문법 본문

Kotlin

[Kotlin] 코틀린 기본 문법

림도현 2025. 4. 27. 12:44

📚 Kotlin - 변수(Variables)

Kotlin에서 변수를 선언할 때는 var 또는 val 키워드를 사용해야 합니다.

  • var : 변경 가능한 변수 (mutable)
  • val : 변경 불가능한 변수 (immutable)

💡 Kotlin은 타입 추론(Type Inference)을 지원하기 때문에 타입을 명시하지 않아도 컴파일러가 타입을 자동으로 추론합니다.

코틀린 코드

    var number1 = 10L      // 타입을 명시하지 않아도 Long 타입으로 추론
    val number2: Long = 10L // 타입을 명시적으로 선언

    var number3: Long? = 1_000L // null이 허용되는 변수는 타입 뒤에 `?`를 붙입니다.
    number3 = null             // null 할당 가능

    var person = Person("임도현") // 객체 생성 시 `new` 키워드를 사용하지 않습니다.

자바 코드

    long number1 = 10L;
    final long number2 = 10L; 

    Long number3 = 1_000L; 
    Person person = new Person("최태현"); 

❗ 참고사항

  • Null 허용: 타입? 형태로 선언하면 해당 변수는 null을 가질 수 있습니다. Kotlin에서는 null 가능성과 불가능성을 타입 시스템 수준에서 구분합니다.
  • new 키워드 생략: Kotlin에서는 객체를 생성할 때 new 키워드를 사용하지 않습니다.

📚 Kotlin - Null 다루기 Safe Call, Elvis 연산자

Kotlin에서는 null 안정성(Null Safety)을 언어 차원에서 지원합니다.
즉, 컴파일 타임에 null 가능성을 체크해주기 때문에 NullPointerException(NPE) 발생 가능성을 크게 줄일 수 있습니다.

💡 Java에서는 런타임까지 가야 NPE가 터지지만, Kotlin은 아예 코드 작성 단계에서 null 여부를 관리합니다.


✏️ 기본 예제

fun main() {

    // Kotlin에서는 null이 가능한 타입을 명시적으로 선언해야 합니다
    val str: String? = "ABC"
    println(str?.length)
    // Safe Call (`?.`) : str이 null이 아니면 length 호출, null이면 그냥 null 반환

    val str2: String? = "ABC"
    println(str2?.length ?: 0)
    // Elvis 연산자 (`?:`) : 앞이 null이면 뒤에 지정한 기본값(0)을 반환
}

✏️ 다양한 Null 처리 방식 예제 함수들

fun startWithA1(str: String?): Boolean {
    // null이면 예외를 던짐
    return str?.startsWith("A") ?: throw IllegalArgumentException("null이 들어왔습니다")
}

fun startsWithA2(str: String?): Boolean? {
    // null이면 null 반환
    return str?.startsWith("A")
}

fun startsWithA3(str: String?): Boolean {
    // null이면 false 반환
    return str?.startsWith("A") ?: false
}

fun startWith(str: String?): Boolean {
    // 절대 null이 아님을 확신할 때 `!!` 사용 (주의: 런타임 NPE 발생 가능성 있음)
    return str!!.startsWith("A")
}

✏️ 자바 코드

public boolean startsWithA1(String str) {
    if (str == null) {
        throw new IllegalArgumentException("null이 들어왔습니다");
    }
    return str.startsWith("A");
}


public Boolean startsWithA2(String str) {
    if (str == null) {
        return null;
    }
    return str.startsWith("A");
}


public boolean startsWithA3(String str) {
    if (str == null) {
        return false;
    }
    return str.startsWith("A");
}

✅ Kotlin으로 변환할 때 장점

  • 코드가 훨씬 짧고 읽기 쉽다
    → if문으로 null 체크하는 코드가 사라지고 ?., ?: 같은 표현식으로 깔끔하게 작성 가능
  • Null 안전성이 강화된다
    → 컴파일 단계에서 null 가능성을 체크해주기 때문에 런타임 에러를 줄일 수 있다
  • 표현이 의도에 더 직관적이다
    !!, ?., ?:를 통해 개발자의 의도를 코드에 명확하게 드러낼 수 있다
  • Elvis 연산자(?:) 덕분에 기본값 처리도 쉬워진다

🏷️ 요약

  • ?. (Safe Call) : null이 아닐 때만 메서드 호출
  • ?: (Elvis 연산자) : null일 때 기본값을 반환
  • !! (Not-Null 단정) : 무조건 null이 아님을 보장 (주의해서 사용!)
  • Kotlin은 NullPointerException을 예방하기 위한 다양한 안전장치를 제공한다.

📚 Kotlin - 3가지 타입

Kotlin의 특이한 3가지 타입 Any - Unit - Nothing


1️⃣ Any

  • Kotlin의 모든 타입의 최상위 타입입니다. (JavaObject와 비슷)
  • Any 타입에는 equals(), hashCode(), toString() 메서드가 기본적으로 정의되어 있습니다.
  • 기본적으로 null을 포함할 수 없습니다.
    null을 허용하려면 Any?로 선언해야 합니다.

예시

fun printAgeIfPerson(obj: Any) {
    if (obj is Person) { // obj가 Person 타입이라면
        val person = obj as Person // 명시적 타입 캐스팅 obj에 Person객체가 들어감
        println(person.age)
    }

    // 또는 스마트 캐스트로 더 간단하게 작성 가능
    if (obj is Person) {
        println(obj.age)
    }
}

fun printAgeIfPerson2(obj: Any?) {
    val person = obj as? Person // 안전한 캐스팅 (null 가능) Person객체가 null이면 null반환
    println(person?.age)
}

💬 스마트 캐스트
if (obj is Person)과 같이 타입 체크를 하면 Kotlin이 자동으로 타입 캐스팅을 해줍니다.
as?를 사용하면 타입이 다르거나 null이어도 예외 없이 null을 반환합니다.


2️⃣ Unit

  • Kotlin에서 Unit은 Java의 void와 비슷한 역할을 합니다.
  • 하지만 Java의 void타입이 아예 없지만, Kotlin의 Unit진짜 존재하는 타입입니다.
  • 함수가 아무 값도 반환하지 않을 때 반환 타입으로 사용합니다.
  • Unit은 단 하나의 인스턴스만 존재합니다 (object처럼).

예시

fun printHello(): Unit { // Unit은 반환 타입을 적지 않으면 자동으로 Unit이 들어감 
    println("Hello, Kotlin!")
}

fun printHello() { // : Unit 생략 가능
    println("Hello, Kotlin!")
}

// Unit을 타입 인자로 사용할 수도 있음
val func: () -> Unit = { println("Lambda function!") }

💬 함수형 프로그래밍에서 Unit의 의미
→ 단 하나의 값만 갖는 타입을 의미합니다. (void와는 개념이 다름)


3️⃣ Nothing

  • Nothing정상적으로 값을 반환하지 않는 함수를 표현할 때 사용합니다.
  • 예외를 던지는 함수나 무한 루프를 도는 함수가 여기에 해당합니다.
  • Nothing은 어떤 값도 가질 수 없으며, 모든 타입의 하위 타입입니다.

예시

fun fail(message: String): Nothing {
    throw IllegalArgumentException(message)
}

fun infiniteLoop(): Nothing {
    while (true) {
        // 무한 루프
    }
}

💬 Nothing은 언제 사용할까?

  • 함수가 절대 정상 종료되지 않을 때
  • 코드를 더 명확하게 표현하고 싶을 때
    (예: 무조건 예외를 발생시키는 유틸 함수)


✅ 요약

타입 설명
Any 모든 타입의 최상위 타입. Object처럼 동작하지만 null을 포함하지 않음 (Any? 필요)
Unit 반환값이 없는 함수에서 사용. 실제 존재하는 타입 (단 하나의 인스턴스)
Nothing 정상 종료되지 않는 함수에서 사용. 예외 발생 또는 무한 루프 등에 사용

📚 Kotlin - 연산자 정리

Kotlin은 기본적인 연산자 사용법이 Java와 매우 유사합니다.
하지만, 객체에 대해서도 연산자 오버로딩(Operator Overloading) 을 지원해서 더욱 자연스럽게 사용할 수 있습니다.


1️⃣ 기본 연산자

  • 단항 연산자 (+, -, ++, --, !)
  • 산술 연산자 (+, -, *, /, %)
  • 산술 대입 연산자 (+=, -=, *=, /=, %=)
  • 비교 연산자 (>, <, >=, <=, ==, !=)

✅ 모두 Java와 사용법이 동일합니다!


2️⃣ 비교 연산자와 compareTo

Kotlin에서는 객체끼리 비교할 때 비교 연산자(>, <, >=, <=)를 사용할 수 있습니다.

  • 비교 연산자를 사용하면 자동으로 compareTo 메서드를 호출합니다.
  • compareTo는 Kotlin에서 Comparable 인터페이스를 구현하면 됩니다. (Java와 비슷)

예제

fun main() {
    val money1 = JavaMoney(2_000L)
    val money2 = JavaMoney(1_000L)

    // 객체 비교: 자동으로 compareTo() 호출
    if (money1 > money2) {
        println("money1이 money2보다 큽니다.")
    }
}

JavaMoney 클래스 (Java)

public class JavaMoney implements Comparable<JavaMoney> {
    private final long amount;

    public JavaMoney(long amount) {
        this.amount = amount;
    }

    public JavaMoney plus(JavaMoney other) {
        return new JavaMoney(this.amount + other.amount);
    }

    @Override
    public int compareTo(JavaMoney o) {
        return Long.compare(this.amount, o.amount);
    }

    // equals, hashCode, toString 생략
}

💬 비교 연산자를 객체에도 사용할 수 있다는 것!
money1 > money2 → 내부적으로 money1.compareTo(money2) > 0 호출


3️⃣ 동일성(===)과 동등성(==)

Kotlin에서는 =====가 구분되어 있습니다.

연산자 의미 Java 대응
== 동등성 (equals 호출) equals()
=== 동일성 (참조 비교) == (주소값 비교)

예제

fun main() {
    val money3 = JavaMoney(1_000L)
    val money4 = money3
    val money5 = JavaMoney(1_000L)

    println(money3 === money4) // true (같은 객체)
    println(money3 == money5)  // true (값이 같음, equals 호출)
}

💬 Kotlin에서 ==을 사용하면 자동으로 equals()를 호출합니다.
반면에 ===은 참조(주소)를 비교합니다.


4️⃣ 연산자 오버로딩 (+)

Kotlin에서는 연산자 오버로딩을 통해, 객체끼리 +, - 같은 연산자를 직접 사용할 수 있습니다.

  • 객체에 plus 함수를 정의하면 + 연산자를 사용할 수 있습니다.

예제

fun main() {
    val money1 = JavaMoney(2_000L)
    val money2 = JavaMoney(1_000L)

    println(money1.plus(money2)) // 일반 호출
    println(money1 + money2)      // 연산자 호출 (plus 자동 연결)
}

✅ 요약

구분 설명
기본 연산자 Java와 사용법 동일 (+, -, *, /, %)
객체 비교 비교 연산자 사용 시 compareTo 자동 호출
동일성/동등성 === (동일성, 주소 비교), == (동등성, equals 호출)
연산자 오버로딩 plus, minus 등의 메서드를 통해 +, - 연산 가능

📌 정리

코틀린에서는

  • 객체끼리도 자연스럽게 >, < 같은 비교 연산 가능
  • ==를 쓰면 자동으로 equals() 호출
  • + 연산자도 오버로딩해서 객체끼리 덧셈 지원 가능

덕분에 더 직관적이고 간결한 코드 작성이 가능합니다! 🚀


📚 Kotlin - if문, when문 정리

Kotlin은 Java와 비교해서 제어문(if, when)을 훨씬 간결하고 표현력 있게 사용할 수 있습니다.
특히 Kotlin에서는 if문과 when문이 "Expression(표현식)" 이라는 점이 큰 특징입니다.


1️⃣ Kotlin의 if문

  • Kotlin의 if문Java와 문법이 거의 동일합니다.
  • if문 자체가 Expression이다.
    • 값처럼 사용할 수 있어서 삼항 연산자(조건 ? A : B) 가 따로 존재하지 않는다!

✅ Kotlin if문 예시

fun getPassOrFail(score: Int): String {
    return if (score >= 50) {
        "P"
    } else {
        "F"
    }
}

if 블록이 끝나면 그 결과가 반환되어 바로 return이 가능!

✅ Kotlin 다중 조건 if문 예시

fun getGrade(score: Int): String {
    return if (score >= 90) {
        "A"
    } else if (score >= 80) {
        "B"
    } else if (score >= 70) {
        "C"
    } else {
        "D"
    }
}

2️⃣ Kotlin의 when문

  • Java의 switch문을 Kotlin에서는 when문으로 대체합니다.
  • when문 역시 Expression입니다! (결과를 반환 가능)
  • when값 뿐만 아니라 조건식도 받을 수 있다.

✅ Kotlin when 기본 사용

fun getGradeWithSwitch(score: Int): String {
    return when (score / 10) {
        in 9..10 -> "A" // // 90 ~ 99 까지이면 A출력
        in 8..9 -> "B"
        in 7..8 -> "C"
        else -> "D"
    }
}

✅ Kotlin when 타입 체크 사용

fun startWithA(obj: Any): Boolean {
    return when (obj) {
        is String -> obj.startsWith("A") // // obj가 String 이면 startsWith 검사 아니면 false 반환 
        else -> false
    }
}

💬 is 키워드를 통해 타입 체크도 자연스럽게 가능!


3️⃣ Java vs Kotlin 비교

🔥 Java 코드 (if문)

private void judgeNumber2(int number) {
    if (number == 0) {
        System.out.println("주어진 숫자는 0입니다");
        return;
    }
    if (number % 2 == 0) {
        System.out.println("주어진 숫자는 짝수입니다");
        return;
    }
    System.out.println("주어지는 숫자는 홀수입니다");
}

🔥 Kotlin 코드 (when문)

fun judgeNumber2(number: Int) {
    when {
        number == 0 -> println("주어진 숫자는 0입니다.")
        number % 2 == 0 -> println("주어진 숫자는 짝수입니다.")
        else -> println("주어지는 숫자는 홀수입니다.")
    }
}

💬 Kotlin은 when 블록을 이용해 여러 조건을 자연스럽게 분기할 수 있다.
따로 return을 안 써도, 순차적으로 평가되어 필요한 블록만 실행!


✅ 요약

구분 Kotlin 특징
if문 Expression(값처럼 사용 가능)
삼항 연산자 존재하지 않음 (if로 대체)
when문 switch문을 대체, 더 강력한 기능
when문 특징 값뿐만 아니라, 타입 체크, 조건식까지 사용 가능
다중 조건 when으로 깔끔하게 분기 가능

📌 정리

  • Kotlin의 if문, when문값을 반환하는 Expression이다!
  • 삼항 연산자 없이 if를 값처럼 사용할 수 있다.
  • when문은 switch보다 더 강력하며, 타입 체크나 범위 조건까지 지원한다.
  • Java에 비해 코드가 훨씬 간결하고 명확해진다.

Kotlin은 "모든 것이 Expression"이라는 설계 철학 덕분에, 더 깔끔하고 함수형 스타일 코드를 작성할 수 있습니다! 🚀


📚 Kotlin - 반복문 (for문, for-each문, while문) 정리

Kotlin은 반복문을 Java보다 더 간결하고 직관적으로 표현할 수 있습니다.
특히 in 키워드등차수열(range) 을 이용해 편리하게 사용할 수 있어요.


1️⃣ Kotlin의 for-each문

  • Java에서는 :을 사용하지만, Kotlin에서는 in 키워드를 사용합니다.

✅ Kotlin for-each문 예시

fun main() {
    val numbers = listOf(1L, 2L, 3L)

    for (number in numbers) {
        println(number)
    }
}

💬 in을 통해 컬렉션의 요소를 순회합니다.


2️⃣ Kotlin의 전통적인 for문

  • Kotlin은 전통적인 for문 대신 등차수열(Range) 을 사용합니다.
  • .. 연산자로 범위를 생성합니다.

✅ 오름차순 반복 (1부터 3까지)

for (i in 1..3) {
    println(i)
}
  • 1..3 : 1부터 3까지 포함 (inclusive)

✅ 내림차순 반복 (3부터 1까지)

for (i in 3 downTo 1) {
    println(i)
}
  • downTo 키워드를 사용하면 역방향으로 순회합니다.

✅ step을 사용한 반복 (2칸씩 이동)

for (i in 1..5 step 2) {
    println(i)
}
  • step 키워드로 증가 폭을 설정할 수 있습니다.

3️⃣ while문, do-while문

  • while, do-while 문법은 Java와 완전히 동일합니다.

✅ while문 예시

var i = 1
while (i <= 3) {
    println(i)
    i++
}

✅ do-while문 예시

var j = 1
do {
    println(j)
    j++
} while (j <= 3)

💬 do-while조건과 상관없이 최소 1회는 실행됩니다.


✅ 요약

구분 Kotlin 특징
for-each문 in 키워드를 사용
전통적인 for문 1..10 등차수열로 범위를 표현
내림차순 반복 downTo 사용
증가 폭 조정 step 사용
while문, do-while문 Java와 동일

📌 정리

  • Kotlin은 반복문에서 범위(Range) 개념을 자연스럽게 지원한다.
  • for 루프가 훨씬 간결해지고 가독성이 좋아진다.
  • while, do-while은 Java 문법을 그대로 사용 가능하다.

Kotlin의 반복문은 코드량을 줄이고 더 읽기 쉽고 명확한 코드를 만드는 데 큰 도움이 됩니다! 🚀


📚 Kotlin - try-catch 예외처리 정리

Kotlin에서도 try-catch-finally 구문은 Java와 거의 비슷합니다.
하지만 Kotlin만의 특별한 차이점들이 존재합니다.


1️⃣ Kotlin의 try-catch 문법

  • 기본적인 문법 구조는 Java와 동일합니다.
  • catch 블록은 여러 개 작성할 수 있습니다.
  • finally 블록도 지원합니다.
try {
    // 예외가 발생할 수 있는 코드
} catch (e: ExceptionType) {
    // 예외 처리
} finally {
    // 항상 실행되는 블록
}

2️⃣ Kotlin의 try-catch는 Expression

  • Kotlin에서는 try-catch 자체가 Expression입니다.
  • 즉, 값을 반환할 수 있으며 바로 return하거나, 변수에 할당할 수 있습니다.

✅ 예시 1 : return에 사용하는 경우

fun parseIntOrThrow(str: String): Int {
    try {
        return str.toInt()
    } catch (e: NumberFormatException) {
        throw IllegalArgumentException("주어진 ${str}은 숫자가 아닙니다.")
    }
}

✅ 예시 2 : 값으로 사용하는 경우

fun parseIntOrThrowV2(str: String): Int? {
    return try {
        str.toInt()
    } catch (e: NumberFormatException) {
        null
    }
}

💬 try-catch 결과 자체를 반환하거나, 변수에 바로 할당할 수 있다!


3️⃣ Kotlin의 예외는 모두 Unchecked Exception

  • Kotlin에서는 모든 예외가 Unchecked Exception입니다.
  • 즉, 명시적으로 throws 선언을 할 필요가 없습니다.
  • Java처럼 throws IOException 같은 예외 선언을 요구하지 않습니다.
fun readFile() {
    // IOException이 발생할 수 있어도 throws 작성 불필요
}

4️⃣ Kotlin의 try-with-resources

  • Java에서는 try-with-resources를 위해 try(resource) 문법을 사용했지만,
  • Kotlin에서는 use 확장 함수를 사용하여 리소스를 자동으로 닫을 수 있습니다.

✅ Kotlin에서 try-with-resources 스타일

BufferedReader(FileReader("test.txt")).use { reader ->
    println(reader.readLine())
}

💬 use 블록이 끝나면 자동으로 close()가 호출됩니다.


✅ 요약

구분 Kotlin 특징
try-catch 문법 Java와 동일
try-catch Expression, 값을 반환할 수 있음
예외 타입 모두 Unchecked Exception (throws 불필요)
리소스 관리 use 확장 함수로 대체 (try-with-resources)

📌 정리

  • Kotlin에서는 try-catch 문을 값처럼 사용할 수 있다는 점이 큰 차이입니다.
  • Checked Exception이 없기 때문에, 코드를 훨씬 깔끔하게 작성할 수 있습니다.
  • 자원 관리를 use를 통해 훨씬 자연스럽게 처리할 수 있습니다.

Kotlin의 예외처리는 Java보다 간결하고 유연하게 동작합니다! 🚀


📚 Kotlin - 함수 다루기 정리

Kotlin에서는 함수 선언과 사용법이 Java와 많이 다릅니다.
간결함과 표현력을 강화한 Kotlin 함수 문법을 정리합니다!


1️⃣ 함수 선언 문법

  • fun 키워드를 사용해 함수를 선언합니다.
  • 반환 타입은 : 뒤에 명시합니다.
  • Block 대신 =로 단일 표현식을 바로 반환할 수 있습니다.
// 일반 함수 선언
fun max(a: Int, b: Int): Int {
    return if (a > b) a else b
}

// 한 줄로 간결하게
fun max2(a: Int, b: Int): Int = if (a > b) a else b

💬 함수가 "하나의 값"을 반환할 때는 {} 블록 없이 =를 사용합니다!


2️⃣ 기본값(Default Parameter)

  • 함수 파라미터에 기본값을 설정할 수 있습니다.
  • 호출 시 해당 값을 생략하면 기본값이 자동으로 사용됩니다.
fun repeat(str: String, num: Int = 3, useNewLine: Boolean = true) {
    for (i in 1..num) {
        if (useNewLine) {
            println(str)
        } else {
            print(str)
        }
    }
}

// 기본값을 사용한 호출
repeat("Hello World") // num, useNewLine은 설정한 기본값이 들어감 

// 기본값 일부 수정 (Named Argument)
repeat("Hello World", useNewLine = false)

💬 기본값이 있는 파라미터는 생략 가능하며, 특정 파라미터만 지정해서 호출할 수도 있습니다!


3️⃣ Named Argument (이름 있는 인자)

  • Kotlin에서는 호출 시 인자의 이름을 직접 지정할 수 있습니다.
fun printNameAndGender(name: String, gender: String) {
    println(name)
    println(gender)
}

// 이름을 명시하여 호출
printNameAndGender(name = "임도현", gender = "MALE")

💬 매개변수가 많거나, 가독성을 높이고 싶을 때 유용합니다!


4️⃣ 가변인자 (Vararg)

  • 여러 개의 값을 받는 가변 인자를 선언할 수 있습니다.
  • Kotlin에서는 vararg 키워드를 사용합니다.
  • 배열을 넘길 때는 * 스프레드 연산자를 붙여야 합니다.
fun printAll(vararg strings: String) {
    for (str in strings) {
        println(str)
    }
}

// 직접 여러 인자 전달
printAll("A", "B", "C")

// 배열을 전달할 때는 *을 사용
val array = arrayOf("A", "B", "C")
printAll(*array)

fun printAll(vararg strings: String) {
    for(str in strings) {
        println(str)
    }
}

자바 코드

 public static void printAll(String... strings) {
    for (String str : strings) {
      System.out.println(str);
    }
  }

💬 Java의 String... strings와 동일한 개념입니다. Kotlin은 vararg + *로 처리합니다!


✅ 요약

항목 Kotlin 특징
함수 선언 fun 키워드 사용
단일 표현식 반환 = 키워드로 가능
기본값 파라미터 기본값을 선언 가능
Named Argument 호출 시 파라미터 이름 지정 가능
가변 인자 vararg 사용, 배열은 * 붙여야 함

📌 마무리

  • Kotlin의 함수는 짧고 명확하게 작성할 수 있습니다.
  • 표현식 기반이라 더욱 강력한 문법을 제공합니다.
  • 기본값, 이름있는 호출, 가변인자 등을 통해 함수 호출이 매우 유연해집니다.

Kotlin 함수 문법을 잘 활용하면 코드가 훨씬 간결하고 가독성 좋게 변합니다! 🚀