728x90

https://kotlinlang.org/docs/control-flow.html

 

Conditions and loops | Kotlin

 

kotlinlang.org

 

Conditions and loops

If expression

코틀린에서는 if는 표현식이다.(값을 반환할 수 있다.)

그렇기에 코틀린에서는 삼항 연산자(condition ? then : else)가 없다.

If가 이 역할을 하기 때문이다.

fun main(){
    val a = 1
    val b = 2
    
    var max = 0
    
    max = if (a > b) a else b
    
    val maxOr100 = if (a > 100) a else if(b > 100) b else 100
}

 

When expression

When은 다양한 곳을 분기할 수 있는 조건식을 정의한다.

C언어에서의 switch라고 생각하면 된다.

fun main(){
    val x = 0
    
    when(x){
        0 -> println("x is 0")
        1 -> println("x is 1")
        2 -> println("x is 2")
        else -> println("x is neither 1 nor 2")
    }
}

When은 만족하는 condition이 있을 때까지 순서대로 매칭해 간다.

else는 아무것에도 해당하지 않을 때를 정의한다.

 

만약 When이 표현식으로 사용된다면 Else branch는 필수적이다.

그래도 컴파일러가 모든 경우의 수를 커버하고 있다고 알 수 있으면, Else는 생략 가능하다.

enum class Bit{
    ZERO, ONE
}

fun main(){
    val a = Bit.ZERO
    
    when(a){
        Bit.ZERO -> println("Bit.ONE")
        Bit.ONE -> println("Bit.TWO")
    }
}

 

값이 범위 안에 속하는지도 확인할 수 있다.

fun main(){
    val a = 5
    
    when(a){
        in 1..10 -> println(a)
        else -> println("else")
    }
}

 

여기서도 is로 타입을 검사하면 스마트캐스팅이 되어 추가적으로 검사할 필요가 없다.

fun hasPrefix(x: Any) = when(x) {
    is String -> x.startsWith("prefix")
    else -> false
}

 

For loops

for는 iterator를 순환합니다.

for (item in collection) print(item)

 

숫자를 반복하고 싶다면, range expression을 사용한다.

for (i in 1..3) {
    println(i)
}
for (i in 6 downTo 0 step 2) {
    println(i)
}

 

While loops

while과 do-while은 조건이 만족할 때까지 계속 ㅁ반복한다.

while: 조건을 체크하고 그것이 참이면 실행한다. 이것을 반복한다.

do-while: 일단 블록을 실행하고 조건을 체크한다.

while (x > 0) {
    x--
}

do {
    val y = myFunc()
} while (y != null) // y is visible here!

 

Returns and jumps

Returns and jumps

fun main(){
    val a:Int? = null

    val b = (a ?: return).toString()

    println(b)
}

return은 본인이 속한 가장 가까운 함수를 리턴한다

break은 본인이 속한 가장 가까운 loop를 정지한다.

continue는 루프의 다음 스텝으로 넘어간다.

 

Break and continue labels

fun main(){
    loop@ for (i in 1..10) {
        for (j in 1..10) {
            if(i != j) break@loop
            println("$i $j")
        }
    }
}

코틀린에서는 표현식에 label을 붙일 수 있다.

라벨은 @로 끝나며, abc@와 같은 형태가 된다.

break와 continue를 사용하여 해당 부분으로 jump 할 수 있다.

 

Return to labels

fun main(){
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@main
        print(it)
    }
    print(" done with explicit label")
}

이렇게 return에서도 라벨을 사용하여 리턴할 수 있다.

 

Exceptions

예외 처리는 크게 2가지로 나뉜다.

Throwing exceptions: 문제가 발생 했을 때 알린다.

Catching exceptions: 문제가 발생 했을 때 어떤 식으로 처리할 것인지 다룬다.

 

이런 예외 처리는 코드를 더 예측가능하게 도와줄 수 있다.

 

Throw exceptions

throw IllegalArgumentException()

throw 키워드를 사용하여 Exception을 발생시킨다.

Exception이 발생하는 것은 런타임 중에 예상하지 못한 문제가 발생했다는 것을 알리는 것이다.

 

Throw Exceptions with precondition functions

코틀린은 조건을 체크하고 에러를 발생시켜주는 precondition function이 존재한다.

Precondition function Use case Exception thrown
require() 유저의 input이 valid 한지 확인 IllegalArgumentException
check() Object 혹은 변수의 상태가 valid 한지 확인 IllegalStateException
error() 잘못된 상태나 조건을 알린다. IllegalStateException

 

  • require() function
fun getIndices(count: Int): List<Int> {
    require(count >= 0) { "Count must be non-negative. You set count to $count." }
    return List(count) { it + 1 }
}
  • check() function
fun main() {
    var someState: String? = null

    fun getStateValue(): String {

        val state = checkNotNull(someState) { "State must be set beforehand!" }
        check(state.isNotEmpty()) { "State must be non-empty!" }
        return state
    }
    // If you uncomment the line below then the program fails with IllegalStateException
    // getStateValue()

    someState = ""

    // If you uncomment the line below then the program fails with IllegalStateException
    // getStateValue() 
    someState = "non-empty-state"

    // This prints "non-empty-state"
    println(getStateValue())
}

check에서 condition이 false라면 exception을 throw한다.

  • error() function
class User(val name: String, val role: String)

fun processUserRole(user: User) {
    when (user.role) {
        "admin" -> println("${user.name} is an admin.")
        "editor" -> println("${user.name} is an editor.")
        "viewer" -> println("${user.name} is a viewer.")
        else -> error("Undefined role: ${user.role}")
    }
}

fun main() {
    // This works as expected
    val user1 = User("Alice", "admin")
    processUserRole(user1)
    // Alice is an admin.

    // This throws an IllegalStateException
    val user2 = User("Bob", "guest")
    processUserRole(user2)
}

그냥 exception을 발생시켜버린다.

 

Handle exceptions using try-catch blocks

exception이 발생하면, 그래도 프로그램을 이어가기 위해 exception을 handling 해야 한다.

그럴 때 try-catch를 사용한다.

try {
    // exception을 발생시키는 코드
} catch (e: YourException) {
    // exception을 handling 하는 코드
}

 

또한 if와 마찬가지로 try-catch는 expression으로 사용 할 수 있다.

fun main() {
    val num: Int = try {
    	10/0
    } catch (e: ArithmeticException) {
        -1
    }
    println("Result: $num")
}

 

또, 하나의 try에 대하여 여러개의 Catch를 작성 할 수 있다.

 

The finally block

finally block은 무조건 실행되는 부븐이다.

이 finally block은 try에서 exception이 발생하더라도 무조건 실행된다.

그렇기에 finally는 네트워크나 파일과 같은 리소스를 Close 하는 것에서 중요하다.

try {
    // Exception이 발생 할 수 있는 코드
}
catch (e: YourException) {
    // Exception을 handling 하는 코드
}
finally {
    // 무조건 실행되어야 하는 코드
}

이 finally 블록은 catch 블록을 작성하지 않아도 작성할 수 있다.

 

 

'Spring > 코틀린' 카테고리의 다른 글

Idioms  (1) 2024.10.01
Basic syntax  (0) 2024.09.28
코틀린 시작  (0) 2024.09.28
728x90

https://kotlinlang.org/docs/basic-types.html

 

Basic types | Kotlin

 

kotlinlang.org

 

  • Basic types

코틀린에서도 모든 것은 객체이다.

호출하는 함수와 그 어떤 속성도 모두 객체이다.

 

Integer types

코틀린에서는 4가지의 숫자 타입을 제공한다.

Type Size Min Value Max Value
Byte 8 -128 127
Short 16 -32768 32767
Int 32 -2,147,483,648 (-231) 2,147,483,647 (231 - 1)
Long 64 -9,223,372,036,854,775,808 (-263) 9,223,372,036,854,775,807 (263 - 1)

만약 처음에 타입을 지정해주지 않는다면, 컴파일러는 자동으로 Int로 지정해주게 된다.

만약 Int의 범위 밖이라면, 타입은 Long으로 지정되게 된다.

처음에 Long 타입으로 지정해주고 싶다면, 숫자 뒤에 L을 붙여야 한다.

 

val a = 1 // Int
val b = 3030303030303030303030 //Long
val c = 123L // Long

 

Floating-point types

코틀린은 실수에 대해, Float와 Double을 제공한다.
Float은 Single precision, Double은 Double precision

 

Type Size Significant bits Exponent bits Decimal digits
Float 32 24 8 6-7
Double 64 53 11 15-16

 

실수를 선언하면 자동으로 Double로 지정이되며, Float로 지정하고 싶다면 뒤에 f를 붙여주어야 한다.

val e = 2.7182818284 // Double
val eFloat = 2.7182818284f // Float, actual value is 2.7182817

 

Literal constants for numbers

수는 다음과 같이 표현할 수 있다.

- Decimals: 123

- Longs: 123L

- Hexadecimals: 0x0F

- Binaries: 0b00010101

- Doubles by default: 123.5, 123.5e10

 

Numbers representation on the JVM

자바에서는 수를 Int, double로 저장하게 된다.

하지만 이런 타입에는 null이 지정되지 못한다.

그러면 코틀린에서의 Int?는 어떻게 되는 것일까?

그런 경우에는 자바에서의 boxed type인 Integer, Double을 사용했었다.

 

nullable 타입은 같은 수라도 다른 object를 참조한다.

fun main() {
    val a: Int = 100
    val boxedA: Int? = a
    val anotherBoxedA: Int? = a

    val b: Int = 10000
    val boxedB: Int? = b
    val anotherBoxedB: Int? = b

    println(boxedA === anotherBoxedA) // true
    println(boxedB === anotherBoxedB) // false
}

 

이런 일이 생기는 이유는 ~128~127의 범위는 JVM이 메모리 최적화를 위해 같은 곳을 참조하도록 하기 때문이다.

하지만 b의 경우에는 그런 일이 생기지 않는다.

 

Explicit number conversions

다른 표현 방식 때문에, smaller type은 bigger의 subtype이 아니다.

따라서 아래와 같은 경우 문제가 발생한다.

// Hypothetical code, does not actually compile:
val a: Int? = 1 // A boxed Int (java.lang.Integer)
val b: Long? = a // Implicit conversion yields a boxed Long (java.lang.Long)
print(b == a) // Surprise! This prints "false" as Long's equals() checks whether the other is Long as well

 

그렇기 때문에 Smaller type은 bigger 타입으로 자동 캐스팅이 되지 않는다.

따라서 명시적인 변환을 거쳐야 한다.

val b: Byte = 1 // OK, literals are checked statically
// val i: Int = b // ERROR
val i1: Int = b.toInt()

 

Operations on numbers

코틀린은 +, -, *, /, %와 같은 기본 연산자를 지원한다.

 

Division of integers

Int 끼리의 나누기는 항상 Int를 반환한다.

소숫점 부분은 무시된다.

val x = 5 / 2
//println(x == 2.5) // ERROR: Operator '==' cannot be applied to 'Int' and 'Double'
println(x == 2)

 

소숫점까지 구하기 위해서는 하나를 명시적으로 float 타입으로 변환해주어야 한다.

val x = 5 / 2.toDouble()
println(x == 2.5)

 

  • Unsigned integer types

Unsigned integer types

Integer type에 더해, 코틀린은 unsigned 값들을 제공한다.

Type Size Min value Max value
UByte 8 0 255
UShort 16 0 65,535
UInt 32 0 4,294,967,295
ULong 64 0 18,446,744,073,709,551,615

 

Unsigned arrays and ranges

다른 원시 타입들과 같이, 해당 데이터 타입들도 배열을 제공한다.

UByteArray: and array of unsigned bytes

UShortArray: an array of unsigned shorts

UIntArray: an array of unsigned ints

ULongArray: an array of unsigned longs

Unsigned integers literals

unsigned 타입을 더 명확하게 사용하기 위해, 코틀린은 해당 suffix를 제공한다.(Float, Long과 같이)

뒤에 u, U를 붙이면 해당 unsigned 타입으로 컴파일러가 인지하게 된다.

val b: UByte = 1u  // UByte, expected type provided
val s: UShort = 1u // UShort, expected type provided
val l: ULong = 1u  // ULong, expected type provided

val a1 = 42u // UInt: no expected type provided, constant fits in UInt
val a2 = 0xFFFF_FFFF_FFFFu // ULong: no expected type provided, constant doesn't fit in UInt

 

  • Booleans

Boolean 타입은 true, false 이렇게 두가지만 가지는 boolean object이다.

 

다른 언어와 마찬가지로

|| : disjunction(Logical OR)

&&:: conjunction (Logical AND)

!: negation(Logical NOT)

 

val myTrue: Boolean = true
val myFalse: Boolean = false
val boolNull: Boolean? = null

println(myTrue || myFalse)
// true
println(myTrue && myFalse)
// false
println(!myTrue)
// false
println(boolNull)
// null

 

||, &&는 Lazy하게 동작하기도 한다.

무슨말이냐면, first operand가 true라면 OR는 second operand를 확인하지 않는다.

마찬가지로, first operand가 false라면 and는 second operand를 확인하지 않는다.

 

  • Charaters

Character는 작은따옴표 안에 있는 문자 하나를 말한다. ex) '1'

backslash로 시작하는 Special Character가 존재한다.

아래와 같은 역할을 한다.

\t: tab

\b: backspace

\n: new line

\r: carriage return

\': single quotation mark

\": double quotation mark

\\: backslash

\$: dollar sign

 

  • Strings

String은 문자열이며, JVM에서 UTF-16을 사용하기 때문에 문자 하나당 2bytes를 사용한다.

String은 큰따옴표 안에 존재한다.

 

String은 immutable로 후에 바꿀 수 없기 때문에 새로운 문자열 객체를 만들어서 대입해야 한다.

String은 +를 사용하여 문자열들을 이을 수 있다.

 

val s = "abc" + 1
println(s + "def")
// abc1def

 

 

  • Strings

Array는 같은 타입이거나 그것들의 sub 타입 객체들을 고정된 숫자로 가지고 있는 자료구조이다.

 

Create arrays

코틀린에서 배열을 생성하기 위해서는 다음과 같은 함수들을 사용한다.

arrayOf(), arrayOfNulls(), emptyArray()

 

arrayOf()는 괄호 안에 value들을 넣어서 생성한다.

// Creates an array with values [1, 2, 3]
val simpleArray = arrayOf(1, 2, 3)
println(simpleArray.joinToString())
// 1, 2, 3

 

arrayOfNulls를 사용하면 해당 사이즈를 가지는 null 배열을 생성한다.

// Creates an array with values [null, null, null]
val nullArray: Array<Int?> = arrayOfNulls(3)
println(nullArray.joinToString())
// null, null, null

 

emptyArray는 빈 배열을 생성한다.

 

Nested arrays

Array도 객체이기 때문에 다른 Array 안에 들어 갈 수 있다.

// Creates a two-dimensional array
val twoDArray = Array(2) { Array<Int>(2) { 0 } }
println(twoDArray.contentDeepToString())
// [[0, 0], [0, 0]]

 

Access and modify elements

Array는 mutable하기 때문에 수정이 가능하다.

접근 할 때도 []를 사용하여 접근 할 수 있다.

simpleArray[0] = 10
twoDArray[0][0] = 2

 

Work with arrays

Pass variable number of arguments to a function

코틀린에서는 vararg를 통해, 가변 개수의 parameter를 받을 수 있다.

이런 방법은 사전에 정해지지 않은 수의 파라미터를 받는 경우에 굉장히 유리하다.

 

이런 vararg를 사용하는 함수에 array를 통해 가변 개수의 parameter를 넘기려면 *을 사용한다.

배열에 있는 각각의 객체를 spread해서 넘겨주는 연산자이다.

 

fun main() {
    val lettersArray = arrayOf("c", "d")
    printAllStrings("a", "b", *lettersArray)
    // abcd
}

fun printAllStrings(vararg strings: String) {
    for (string in strings) {
        print(string)
    }
}

 

 

Compare arrays

두개의 Array가 같은 순서로 같은 객체들을 가지고 있는지 확인하기 위해서는 .contentEquals()를 사용하면 된다.

val simpleArray = arrayOf(1, 2, 3)
val anotherArray = arrayOf(1, 2, 3)

// Compares contents of arrays
println(simpleArray.contentEquals(anotherArray))
// true

// Using infix notation, compares contents of arrays after an element 
// is changed
simpleArray[0] = 10
println(simpleArray contentEquals anotherArray)
// false

 

 

Transform arrays

코틀린은 array를 transform 하는 것에 많은 함수들을 제공한다.

 

  • Sum

.sum을 사용하여 해당 Array의 element를 모두 더한 값을 리턴한다.

val sumArray = arrayOf(1, 2, 3)

// Sums array elements
println(sumArray.sum())
// 6

 

  • Shuffle

Array에서 해당 elements들을 랜덤하게 섞기 위해서 사용하는 함수이다.

val simpleArray = arrayOf(1, 2, 3)

// Shuffles elements [3, 2, 1]
simpleArray.shuffle()
println(simpleArray.joinToString())

// Shuffles elements again [2, 3, 1]
simpleArray.shuffle()
println(simpleArray.joinToString())

 

  • Convert arrays to collections

Array를 List와 Set으로 변환 할 수 있다.

.toList()와 .toSet()을 사용하면 된다.

val simpleArray = arrayOf("a", "b", "c", "c")

// Converts to a Set
println(simpleArray.toSet())
// [a, b, c]

// Converts to a List
println(simpleArray.toList())
// [a, b, c, c]

 

  • Type checks and casts

is and !is operators

인스턴스가 해당 타입의 객체인지  확인하기 위해서는 is, !is operator를 사용한다.

if (obj is String) {
    print(obj.length)
}

if (obj !is String) { // Same as !(obj is String)
    print("Not a String")
} else {
    print(obj.length)
}

 

Smart casts

컴파일러는 is, !is로 확인 한 경우에는 안전하게 해당 타입으로 캐스팅을 해준다.

그렇기 때문에 개발자가 직접 타입을 as를 사용하여 변환 할 필요가 없다.

fun demo(x: Any) {
    if (x is String) {
        print(x.length) // x is automatically cast to String
    }
}

 

if (x !is String) return

print(x.length) // x is automatically cast to String

 

"Unsafe" cast operator

명시적으로 타입을 캐스팅하고 싶다면 as를 사용한다.

val x: String = y as String

만약 캐스팅이 불가능하다면, Exception이 발생한다.

 

"Safe" (nullable) cast operator

이런 exception을 피하기 위해서는 as? 연산자를 사용한다.

만약 해당 캐스팅이 실패하면 null이 return 되게 된다.

 

val x: String? = y as? String

 

728x90

https://kotlinlang.org/docs/idioms.html

 

Idioms | Kotlin

 

kotlinlang.org

 

Create DTOs (POJOs/POCOs)

코틀린에서는 Data만 가지는 클래스를 Data class라고 따로 정의할 수 있다.

data class User(val name: String, val email: String)

 

여기에서 POJOs, POCOs의 개념이 나오는데

POJO(Plain Old Java Object):  자바 모델이나 기능, 프레임워크 등을 따르지 않은 자바 오브젝트를 지칭하는 말이다.

POCO(Plain Old CLR Object)는 자바가 아닌 닷넨 오브젝트들을 말한다.

Default values for function parameters

fun foo(a: Int = 0, b: String = "") { ... }

 

함수를 선언 할 때, 함수에 기본 값을 줄 수 있다.

foo(1, "123) 이렇게 호출 할 수도 있지만, foo(1) 이렇게 호출 할 수도 있는 것이다.

이런 경우에는 미리 선언해둔 기본값이 들어가게 된다.

 

Filter a list

fun main(){
    val list = listOf(1, 2, 3, 4, 5)

    val filteredList1 = list.filter{
        x -> x > 3
    }

    println(filteredList1)

    val filteredList2 = list.filter{it > 3}

    println(filteredList2)
}

 

리스트에서 조건 filter를 통해, 원하는 값들을 추출 할 수 있다.

이 때 람다 뿐 만 아니라, it을 사용해서도 filter 할 수 있다.

 

Check the presence of an element in a collection

fun main(){

    val emailsList = listOf("trust1204@gmail.com", "trust1204@naver.com")

    if ("trust1204@gmail.com" in emailsList) {
        println("HI trust1204@gmail.com")
    }
}

컬렉션에서 in을 사용하여 해당 값이 컬렉션에 존재하는지 확인 할 수 있다.

String interpolation

fun main(){
    
    val name = "seungkyu"
    
    println("hi $name")
}

$을 통해 문자열 안에 문자열을 끼워 넣을 수 있다.

 

Instance checks

open class A

class B: A()

fun main(){

    val a = A()

    when(a){
        is B -> println("It is B")
        is A -> println("It is A")
        else -> println("I dont know")
    }

}

 

is [Class name]을 통해 해당 클래스의 인스턴스인지 검사 할 수 있다.

 

Read-only list

val list = listOf(1, 2, 3)

이렇게 읽을 수만 있는 리스트를 생성할 수 있다.

이 데이터는 add, put 과 같은 함수로 추가 혹은 수정이 불가능하다. 

Read-only map

val map = mapOf("a" to 1, "b" to 2, "c" to 3)

위와 마찬가지로 읽을 수만 있는 map을 생성할 수 있다.

to로 key와 value를 mapping 한다.

 

Access a map entry

fun main(){
    val map = mapOf("a" to 1, "b" to 2, "c" to 3)

    println(map["a"])

}

이런 식으로 map에 접근하여 데이터를 읽을 수 있다.

 

Traverse a map or a list of pairs

fun main(){
    val map = mapOf("a" to 1, "b" to 2, "c" to 3)

    for((k,v) in map){
        println("$k = $v")
    }

}

map의 key와 value를 반복문으로 한 번에 읽어올 수 있다.

 

Iterate over a range

for (i in 1..10) { ... }  //includes 10
for (i in 1..<10) { ... } //not include 10
for (x in 2..10 step 2) { ... }
for (x in 10 downTo 1) { ... }
(1..10).forEach { ... }

..과 <을 이용해서 iterate의 범위를 정할 수 있다.

Lazy property

fun main(){
    val p: String by lazy { 
        if(0 > 1)
            "Hello World"
        else
            "Hi world"
    }
}

val 타입에서 by lazy로 실행된 이후에 값을 할당 할 수 있다. 

Create a singleton

Object Seungkyu{
	val name = "seungkyu"
}

Object 키워드를 사용하여 싱글톤 객체를 만들 수 있다.

Use inline value classes for type-safe values

@JvmInline
value class UserId(private val id: String)

value 클래스로 만들면, 클래스가 데이터를 직접 참조하기 때문에 객체 생성에 대한 cost를 아낄 수 있다고 한다.

 

Instantiate an abstract class

abstract class InstantiateAnAbstractClass {
    abstract fun doSomething()
    abstract fun sleep()
}

fun main(){
    val myObject = object : InstantiateAnAbstractClass() {
        override fun doSomething() {
            println("It is doSomething")
        }

        override fun sleep() {
            println("It is sleeping")
        }
    }

    myObject.doSomething()
}

이렇게 추상 클래스를 바로 만들 수 있다.

If-not-null shorthand

fun main(){
    val a: String? = "seungkyu!!"

    println(a?.length)
}

null 가능 변수에 ?. 을 붙여서 만약 null이 아니면 가져올 값을 지정할 수 있다.

 

If-not-null-else shorthand

fun main(){
    val a: String? = null

    println(a?.length ?: "hello!!")
}

null이 아닐 때 뿐만 아니라, null 일 때 가져올 값을 지정할 수 있다.

만약 ?: 앞의 값이 null이라면 뒤에 있는 값으로 가져오게 된다.

 

Execute a statement if null

fun main(){
    val values= mapOf<String, Int>()

    println(values["a"] ?: throw NullPointerException())
}

 

?: 를 통해 null 일 때 Exception을 throw 할 수 있다.

 

Get first item of a possibly empty collection

fun main(){
    val emails = listOf<String>()

    val mainEmail = emails.firstOrNull()

    println(mainEmail)
}

이런 식으로 first item을 가져오거나 null을 가져 올 수 있다.

 

Execute if not null

fun main(){
    val value1 = "String"
    val value2:String? = null

    value1?.let {
        println(it)
    }

    value2?.let {
        println(it)
    }
}

?.let을 이용하여 해당 데이터가 null이 아닐 때 실행할 값을 실행할 수 있다.

 

Return on when statement

fun main(){
    println(myFunc(3))
}

fun myFunc(value: Int): String{
    return when(value){
        1 -> "one"
        2 -> "two"
        3 -> "three"
        else -> "no"
    }
}

 

이렇게 함수 Return 부분에서 when을 사용하여 값을 return 할 수 있다.

이 때, 어떠한 경우에도 값이 return 될 수 있도록 꼭 when을 지정해주어야 한다.

 

try-catch expression

fun main(){
    val result = try{
        throw NullPointerException()
    }catch (e: NullPointerException){
        1
    }

    println(result)
}

값을 할당 할 때에도, try-catch Expression을 사용하여 값을 대입할 수 있다.

 

Builder-style usage of methods that return Unit

fun main(){
    arrayOfMinusOnes(10).forEach { print("$it ") }
}

fun arrayOfMinusOnes(size: Int): IntArray {
    return IntArray(size).apply { fill(-1) }
}

return 할 때에도, 자바의 Builder 스타일을 사용해 값을 반환 할 수 있다.

 

Single-expression functions

fun theResult1() = 1111

fun theResult2(value: Int) = when(value){
    1 -> "one"
    2 -> "two"
    else -> "other"
}

fun main(){
    println(theResult1())
    println(theResult2(1))
}

함수를 이렇게 하나의 표현식으로도 작성할 수 있다.

 

Call multiple methods on an object instance (with)

class Bird{
    fun fly(){
        println("Bird fly")
    }

    fun go(x: Int, y: Int){
        println("Bird go $x $y")
    }
}

fun main(){
    val myBird = Bird()

    with(myBird){
        fly()

        for(i in 1..3){
            go(i,i)
        }
    }
}

with를 사용해서 하나의 인스턴스에서 다양한 함수들을 호출 할 수 있다.

 

Generic function that requires the generic type information

inline fun <reified T: Any> hello(value: String): T =  value as T

fun main() {
    
}

타입 정보를 같이 받는 Generic Function을 구현 할 수도 있다.

 

Mark code as incomplete (TODO)

fun main(){
    println("Hello Kotlin")
    TODO("아직이요")
}

TODO를 이용하여 아직 작성하지 않은 코드라고 알릴 수 있다.

 

자동으로 코드를 삽입해주어서, 실행이 가능하다.

물론 TODO()의 코드에 도착하면 그때는 에러가 발생한다.

'Spring > 코틀린' 카테고리의 다른 글

Concepts:Control flow  (1) 2024.10.05
Basic syntax  (0) 2024.09.28
코틀린 시작  (0) 2024.09.28
728x90

거의 1년간 코틀린으로 스프링부트를 사용하고 있었지만, 사실 나의 코틀린은 자바에서 단지 널 안정성만 추가된 언어였다.

 

물론 널 안정성 만으로도 자바에서 코틀린으로 넘어 올 가치는 있지만, 그래도 더 나은 개발자가 되기 위해서는 코루틴까지 자유롭게 사용할 수 있어야 한다는 생각이 들었다.

 

코틀린은 아직 한국어 자료가 많이 없기 때문에 이 참에 공식문서를 참고하여 코틀린을 깊게 공부해보려 한다.

 

https://kotlinlang.org/docs/home.html

 

Kotlin Docs | Kotlin

 

kotlinlang.org

 

'Spring > 코틀린' 카테고리의 다른 글

Concepts:Control flow  (1) 2024.10.05
Idioms  (1) 2024.10.01
Basic syntax  (0) 2024.09.28

+ Recent posts