ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kotlin] toBoolean(), toBooleanStrict()
    📖 개발 공부/kotlin 2023. 7. 26. 22:35
    한줄 요약

    문자열이 "true", "false"인 경우에만 Boolean 타입을 반환하고, 나머지는 예외 던지는 걸 기대한다면, toBoolean()이 아니라 toBooleanStrict() 을 사용하자.

     

     

    코틀린에서 문자열(String)은 타입 변환을 해주는 확장 함수를 제공한다.

    • toByte()
    • toShort()
    • toInt()
    • toLong()
    • toFloat()
    • toDouble()
    • toBoolean()

    테스트 코드를 짜다가 생각치 못한 부분에서 버그를 발견했다.

     

    “random”.toBoolean() 은 어떤 값을 반환할거라 예상하는가? 한번 생각해보자.

     

    나는 당연히 IllegalArgumentException 예외가 던져질 줄 알았다.

    하지만 예상과 다르게, false 를 반환하는 것을 알 수 있다.

    fun main() {
        println("random".toBoolean()) // false
    }

    나는 true나 false인 문자열을 받아서 toBoolean()을 해주고 있었다. 그래서 true, false 이외의 다른 값이 들어오는 경우엔 예외가 던져질 거라고 기대했다.

    이렇게 생각했던 이유는 toInt(), toLong() 같은 경우에는 문자열이 숫자 형태가 아니면 예외를 던지고 있기 때문에 똑같은 동작을 할 거라고 생각했다.

    /**
     * Parses the string as a [Long] number and returns the result.
     * @throws NumberFormatException if the string is not a valid representation of a number.
     * @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
     */
    @SinceKotlin("1.1")
    @kotlin.internal.InlineOnly
    public actual inline fun String.toLong(radix: Int): Long = java.lang.Long.parseLong(this, checkRadix(radix))

    하지만 toBoolean() 내부로 들어가보면 다음과 같은 로직으로 실행되는 것을 알 수 있다.

    /**
     * Returns `true` if this string is not `null` and its content is equal to the word "true", ignoring case, and `false` otherwise.
     *
     * There are also strict versions of the function available on non-nullable String, [toBooleanStrict] and [toBooleanStrictOrNull].
     */
    @JvmName("toBooleanNullable")
    @SinceKotlin("1.4")
    @kotlin.internal.InlineOnly
    public actual inline fun String?.toBoolean(): Boolean = java.lang.Boolean.parseBoolean(this)
    
    public static boolean parseBoolean(String s) {
        return "true".equalsIgnoreCase(s);
    }
    

    위 코드를 보면 대소문자 구별 없이 문자열이 true 인 경우에만 true를 반환하고 나머지는 false를 반환하는 것을 알 수 있다.

    내 예상과는 다르게 동작하는 함수였다. 😱

     

    그래서 따로 확장함수를 구현해야하나 라는 생각하는 찰나에, toBooleanStrict() 함수를 발견했다.

    이는 내가 찾고있던 함수였다. 내부 로직을 보자.

    /**
     * Returns `true` if the content of this string is equal to the word "true", `false` if it is equal to "false",
     * and throws an exception otherwise.
     *
     * There is also a lenient version of the function available on nullable String, [String?.toBoolean].
     * Note that this function is case-sensitive.
     *
     * @sample samples.text.Strings.toBooleanStrict
     */
    @SinceKotlin("1.5")
    public fun String.toBooleanStrict(): Boolean = when (this) {
        "true" -> true
        "false" -> false
        else -> throw IllegalArgumentException("The string doesn't represent a boolean value: $this")
    }
    

    문자열이 true인 경우에만 true, 문자열이 false인 경우에만 false, 나머지는 예외를 던짐.

     

    한줄 요약하자면(인트로랑 똑같음ㅎㅎ)

     

    문자열이 "true", "false"인 경우에만 Boolean 타입을 반환하고, 나머지는 예외 던지는 걸 기대한다면, toBoolean()이 아니라 toBooleanStrict() 을 사용하자.

     

     

    이를 계기로 toBoolean() 함수의 동작을 제대로 이해하고, toBooleanStrict() 확장함수도 알게 되었다. 요것이 바로 테스트코드의 중요성인가 ㅎㅎ

     

    728x90
    반응형

    댓글

Designed by Tistory.