반응형
Heli, 헬리
시행착오를 줄이는 방법 - 진태양
Heli, 헬리
  • 분류 전체보기 (82)
    • General (28)
      • Essay (22)
      • Craftsmanship (2)
      • IT Meet & Hack (4)
    • Finance (1)
      • Portfolio (1)
      • Activity (0)
    • Infrastructure (1)
      • Kubernetes (0)
      • AWS (1)
    • Development (45)
      • News (4)
      • Architecture (4)
      • Web (1)
      • Spring Framework (7)
      • JVM (12)
      • MongoDB (0)
      • Git (2)
      • Algorithm (14)
      • Python (1)
    • Computer Science (1)
      • Network (1)
    • Civic Hacking (3)
      • Code for Korea (3)
    • Know-how (2)
      • IT Service (1)
      • Career (1)
    • English (1)
      • Translation (1)

인기 글

  • 서버 개발자, 커뮤니티 빌더의 이야기가 궁금하신분!
    2023.03.28
    서버 개발자, 커뮤니티 빌더의 이야기가 궁금하신분!
  • Why DDD, Clean Architecture and ⋯
    2022.03.10
    Why DDD, Clean Architecture and ⋯
  • [번역] 개발자가 잠자는 동안 돈을버는 5가지 방법 | 사⋯
    2022.04.17
    [번역] 개발자가 잠자는 동안 돈을버는 5가지 방법 | 사⋯
  • M1 칩에서 pyqt5 설치하기 - qmake 패스 설정
    2022.07.30
  • [Java & Kotlin] enum class가 완벽한 ⋯
    2021.12.13
    [Java & Kotlin] enum class가 완벽한 ⋯

블로그 메뉴

  • 홈
  • 관리
  • 방명록
hELLO · Designed By 정상우.
Heli, 헬리

시행착오를 줄이는 방법 - 진태양

코틀린 기초: 변수, 함수, 반복문 개요
Development/JVM

코틀린 기초: 변수, 함수, 반복문 개요

2022. 2. 13. 13:02
반응형

변수

타입 추론 (Type Inference)

/* 컴파일러가 컴파일 타임에 타입 추론을 통해 타입을 알아낸다 */
val i = 10    // Int
val s = "str" // String

val l1 = 10L
val l2: Long = 10 // 타입을 명시할 수도 있음

변경 가능한 변수 (mutable)

var(variable) 키워드로 선언된 변수는 참조값을 변경할 수 있습니다. 다른 데이터 타입으로의 변경은 불가능합니다.

var x = 10
x = 20 // ok

// 같은 데이터 타입 값만 세팅이 가능하다
x = "test" // (x) compile error

변경 불가능한 변수( immutable )

val(value) 키워드로 선언된 변수에는 단 한 번만 참조값을 세팅할 수 있습니다. (초기값 세팅만 가능)

자바의 final 키워드로 선언한 것과 동일합니다.

val x = 10
x = 20 // (x) compile error

// 선언과 동시에 세팅하라는 의미가 아니다
val isUpper: Boolean // 초기화를 하지 않고 선언하는 경우, type 명시 필수!!
if(x > 0) {
    isUpper = true  // ok
} else {
    isUpper = false // ok
}

isUpper = false // (x) compile error

변수에 세팅된 참조값을 변경할 수 없는 것이기 때문에, 참조가 가르키는 객체의 내용은 변경할 수 있습니다.

val list = arrayListOf(1, 2)
list += 3 // list would be [1, 2, 3]

 

함수

Standard library functions

코틀린에서는 println 함수와 같이 별도의 import 없이 제공하는 API들이 있습니다.

이는 kotlin-stdlib와 default import를 지원하기 때문에 가능한 것입니다.

// println은 kotlin-stdlib::kotlin.io 패키지 하위에 존재
println("Hello, world!")

Default Import

Kotlin 파일에는 기본적으로 임포트되는 패키지들이 존재합니다.

  • kotlin.*
  • kotlin.collections.*
  • kotlin.io.*

Packages and imports | Kotlin

 

Packages and imports | Kotlin

 

kotlinlang.org

kotlin-stdlib 라이브러리는 코틀린 프로젝트 설정에서 확인할 수 있습니다.

Kotlin stdlib API documentation

다음 페이지에서 상세 API 목록과 정의를 찾을 수 있습니다.

kotlin-stdlib - Kotlin Programming Language

 

kotlin-stdlib - Kotlin Programming Language

 

kotlinlang.org

 

Statement vs Expression

코틀린은 statement <-> expression 을 구분하는 관점에서 자바와는 다른 점이 많습니다.

코틀린에서 if 키워드는 식으로 처리됩니다. 다른 언어에서는 보통 if 문이라 부르는 것과 차별이 있는 것인데요. 어떤 차이가 있을까요?

val isZero = if(number == 0) true else false

/* if-else block 가장 아랫 라인이 result에 세팅됨 */
val result =
    if(condition) {
        /* ... */
        "if end" // result = "if end"
    } else {
        /* ... */
        "else end" // result = "else end"
    }

// 대입(=) 키워드는 반대로 expression -> statement로 처리된다
fun isZero(a: Int, b: Int): Int = if(number == 0) true else false

Statement

  • statement는 블록의 상위 요소( 보통 블록을 포함 )
  • 아무런 값을 만들어내지 않음

Expression

  • 다른 expression의 하위 요소로 포함될 수 있습니다.
  • expression의 결과는 값을 생성합니다.

 

Class와 Property

자바에서의 프로퍼티는 Field와 Access Method를 묶어놓은 개념입니다.

코틀린에서는 이를 컴파일러를 통해 언어 기본 기능으로 제공합니다.

  • val 필드 → getter 제공
  • var 필드 → getter/setter 제공

또한 클래스 인스턴스 생성시, 메모리 할당 연산자 new 를 사용하지 않아도 됩니다.

/* Kotlin */
class Human(
    val name: String, // read-only
    var age: Int      // read + write
)

val human = Human("name", 30) // new operator 생략

println("${human.name}: ${human.age}") // public 변수인 것처럼 사용

var value = 1 // Int 타입도 getter/setter를 내부적으로 제공

/* 같은 내용의 Java 코드, 편의상 어노테이션 처리 */
class Human {
    @Getter
    private String name;

    @Getter @Setter
    private int age;
}

커스텀 접근자( Custom Accessor )

커스텀 게터/세터를 만들고 싶은 경우 다음과 같이 사용 할 수 있습니다.

class Rectangle(
    val width: Int,
    val height: Int
) {
    val area: Int
        get() = this.width * this.height
}

 

enum

고전적으로 enum의 경우, switch-case 구문과 사용하기 좋습니다. (코틀린에서는 when)

enum class Direction {
    NORTH, SOUTH, WEST, EAST
}

printDirection(d: Direction) = when(d) {
    Direction.NORTH -> println("north")
    Direction.SOUTH -> println("south")
    Direction.WEST  -> println("west")
    Direction.EAST  -> println("east")
}

Enum 또한 클래스이기 때문에 별도의 필드와 메소드를 가질 수 있습니다.

만약 별도의 필드를 정의한 경우, 마지막 항목 뒤에는 세미콜론(;)을 붙여 구분해주어야 합니다.

enum class Snack(
    val snackName: String,
    val price: Int
) {
    POTATO_CHIP("포테이토칩", 1000),
    SWING_CHIP("스윙칩", 1200),
    CHOCO_CHIP("초코칩", 2500); 

    fun calcPrice(count: Int) = this.price * count
}

fun main(args: Array<String>) {
    val price = Snack.POTATO_CHIP.calcPrice(3)
    println(price)
}

 

when

when 키워드는 Java의 switch statement와 동일한 역할을 합니다.

하지만 if와 마찬가지로 statement가 아닌 expression이므로 값을 반환한다는 차이점이 있습니다.

fun describe(obj: Any): String = when (obj) {
    1 -> "One"
    "Hello" -> "World"
    is Long -> "Long"
    !is String -> "Not a String"
    else -> "Unknown"
}

println(describe(1L)) // "Long" will be printed

/* when문에 파라미터를 세팅하지 않으면, if-else와 같이 사용할 수 있다 */
val items = arrayListOf("banana", "apple")
when {
    ("banana" in items && "apple" in items) -> print("banana")
    "avocado" in items -> print("avocado")
    else -> print("no fruit")
}

 

Smart Casts

개발자가 코드에 type casting을 명시하지 않더라도, 코틀린 컴파일러가 스마트하게 캐스팅을 진행해주는 경우가 있습니다.

is keyword를 통해 객체가 특정 클래스의 인스턴스임을 확인하면, 컴파일러가 자동으로 type casting을 진행하여 컴파일을 진행합니다.

/* Java */
void function(Object obj) {
    if(obj instanceof String) {
        String str = (String)obj;
        System.out.println(str.length() + " : " + str)
    }
}

/* Kotlin */
fun function(x: Any) {
    if(str is String) {
        print("${str.length} : $str")
    }
}

 

Loop

while, do-while 루프

코틀린은 while, do-while 루프를 지원하며, Java와 사용법이 같습니다.

while(condition) {
    /* ... */
}

do {
    /* ... */
} while(condition)

For 루프

코틀린은 range(iterable한 객체)를 통한 이터레이션을 지원합니다.

  • 초기값, 증가값을 의미하는 변수와 조건식이 존재하지 않음

조건에 사용할 수 있는 키워드는 다음과 같습니다.

  • in, until, downTo, step
for(i in 1..10) {
    // 1 <= i <= 10
}

for(ch in 'a'..'z') {
    // 'a' <= ch <= 'z'
}

for(i in 1..10 step 3) {
    // 1, 4, 7, 10
}

/* until은 끝자리 숫자를 제외함을 유의 */
for(i in 1 until 5) { // step 사용 가능
    // 1 <= i < 5
}

for(i in 5 downTo 1) { // step 사용 가능
    // 5, 4, 3, 2, 1
}

/* iterable 객체를 통한 iteration */
val numbers = listOf(1, 2, 3, 4)
for (number in numbers) {
    // 1, 2, 3, 4
}

Range 클래스( x..y ) 분석

x..y도 역시 kotlin-stdlib가 제공하는 하나의 Range 클래스이며, 다양한 종류를 지원하고 있습니다.

  • IntRange, CharRange, ClosedRange, ...

kotlin.ranges - Kotlin Programming Language

 

kotlin.ranges - Kotlin Programming Language

 

kotlinlang.org

 

Range의 구현체 중 IntRange 클래스는 아래와 같이 구성되어 있습니다.

val range = 1..10

/* 아래는 디버깅으로 확인한 클래스 정보 */
range = {IntRange@491} 1..10
        first = 1
        last  = 10
        step  = 1
        endInclusive = {Integer@527} 10
        isEmpty = false

/* 다음 코드를 실행하면, range 변수는 IntRange가 아닌 IntProgression의 객체가 된다
 * 이 내용은 생략 */
val range = 1..10 step 2

 

try, catch, finally

Java와 표현식과 구동 방식이 굉장히 비슷합니다.

fun doThings() {
    try {
        /* ... */
    } catch (e: NumberFormatException) { // 예외 타입을 ':' 오른쪽에 써준다
        /* ... */
    } catch (e: Exception) {
        /* ... */
    } finally {
		// finally는 Java와 동일하게 동작
    }
}

/* 함수가 던지는 예외를 명시하지 않아도 된다 */
fun throwException() {
    /* throws가 아닌 throw를 사용한다 */
    throw IllegalArgumentException("errmsg")
}

try-catch 키워드도 statement가 아닌 expression입니다.

그렇기에 if-else와 동일하게 블럭의 마지막 라인은 결과값으로 반환됩니다.

단, finally 문은 그대로 statement를 유지

/* 아래 try 구문 정상 구동
 *    value -> "Succeed"
 * Exception 발생시
 *    value -> "Fail"
 */
val value = 
    try {
        /* do things... */
        "Succeed"
    } catch(e: Exception) {
        /* do things... */
        "Fail"
    } finally {
        // finally는 statement이므로 결과값에 영향을 주지 않음
    }
반응형
저작자표시 비영리 동일조건

    ☕️ Networking

    기술 직군의 기술적인 교류, 커리어 이야기, 직군 무관 네트워킹 모두 환영합니다!

    위클리 아카데미 오픈 채팅방(비밀번호: 9323)

    kakaotalk: https://open.kakao.com/o/gyvuT5Yd

    'Development/JVM' 카테고리의 다른 글
    • Java Compiler Optimization
    • 코틀린 기초: 함수 정의와 호출
    • 코틀린이란 무엇이며, 왜 필요한가?
    • [Kotlin] 상태를 가변적으로 관리했을 때 발생하는 문제
    기초, 반복문, 변수, 예외 처리, 코틀린, 함수
    Heli, 헬리
    Heli, 헬리
    Java/Kotlin, Spring 백엔드 관련 기술을 익히고 공유합니다.
    코틀린 기초: 함수 정의와 호출
    다음 글
    코틀린 기초: 함수 정의와 호출
    코틀린이란 무엇이며, 왜 필요한가?
    이전 글
    코틀린이란 무엇이며, 왜 필요한가?

    티스토리툴바