Kotlin ลอง & จับข้อยกเว้น

ฉันเป็นโปรแกรมเมอร์ Kotlin มือใหม่มาก ฉันทำอะไรผิดกับ try & catch code? มีปัญหากับชิ้นส่วนลองหรือจับชิ้นส่วนหรือไม่?

fun sumOfDigits(quantity: Int): Int {
    var score = 0
    var digit: Int
    var number: Int = quantity

    if (number < 0) throw ArithmeticException("Give number >0!")

    while (number > 0)
    {
        digit = number%10
        score += digit
        number /=10
    }
    return score
}
fun main()
{
    println("Give number: ")
    var quantity: Int = readLine()!!.toInt()

    try {
        quantity == 0
    }
    catch (e: Exception){
        println("Can't be 0!")
    }
    catch (e: ArithmeticException){
        println(e.message)
    }
    println(sumOfDigits(quantity))
}

person Ozzini    schedule 16.12.2020    source แหล่งที่มา
comment
quantity == 0 ไม่ใช่คำสั่งที่ถูกต้องในตัวมันเอง   -  person AvroVulcan    schedule 16.12.2020
comment
คุณจะต้องมี if (quantity == 0) println("Can't be 0!") นอกจากนี้ การจับครั้งที่สองก็ไม่มีประโยชน์เนื่องจาก toInt จริงอยู่นอกบล็อก try   -  person user    schedule 16.12.2020


คำตอบ (1)


มีแนวคิดบางประการที่คุณเข้าใจผิด

เริ่มต้นด้วยการพูดถึงเรื่องนี้:

 try {
        quantity == 0
    }
    catch (e: Exception){
        println("Can't be 0!")
    }
    catch (e: ArithmeticException){
        println(e.message)
    }
    println(sumOfDigits(quantity))

ประเด็นบางประการ ประการแรก assignment ซึ่งจริงๆ แล้วคือ check

quantity == 0 จะไม่เปลี่ยนค่าของ quantity แต่จะตรวจสอบว่ามีค่าเท่ากับ 0 หรือไม่ ผลลัพธ์ของการตรวจสอบนี้ (a Boolean) จะถูกละเว้นโดยสิ้นเชิง

หากคุณต้องการตรวจสอบว่า quantity เป็น 0 หรือไม่ คุณต้องดำเนินการในคำสั่ง if

ความสับสนประการที่สองที่ฉันคิดว่าคุณมีคือเกี่ยวกับสิ่งที่ try/catch บล็อกทำ มันลองใช้โค้ดบางชิ้น และหากโค้ดนั้นล้มเหลว (หรือที่เรียกว่าโค้ดทำให้เกิดข้อยกเว้น) สามารถใช้ catch เพื่อลดความเสี่ยงของการหยุดกระบวนการได้ ในบางกรณี มันเป็นเรื่องปกติที่กระบวนการจะหยุด จากนั้น catch จะถูกใช้เพื่อเขียนข้อมูลเพิ่มเติมในคอนโซล เพื่อแทนที่ข้อความของข้อยกเว้น หรือเพื่อเรียกโค้ดส่วนอื่นๆ ก่อนที่กระบวนการจะสิ้นสุดลง

ความสับสนประการที่สามอยู่ที่บล็อก catch catch (e: Exception) จะตรวจจับข้อยกเว้นที่เป็นไปได้ทั้งหมด (แต่ไม่ใช่ทั้งหมดที่เป็นไปได้ Throwables) นั่นหมายความว่าบล็อก catch ที่สองของ e: ArithmeticException จะไม่เกิดขึ้นเลย เนื่องจากบล็อกแรกเป็นแบบทั่วไปมากกว่า

เมื่อพิจารณาแล้ว และสมมติว่าคุณต้องการให้กระบวนการหยุดจริง ๆ เมื่ออินพุตเป็น 0 สิ่งที่คุณต้องทำคือ:

if(condition==0) return //close the program silently

OR

if(condition==0) error("Can't be 0") //throw an exception with this message

แต่ sumOfDigits ของคุณตรวจสอบแล้วว่าตัวเลขนั้นน้อยกว่า 0 หรือไม่ ทำไมไม่ลองดูว่ามันน้อยกว่า 1 ล่ะ? เนื่องจากเราไม่ต้องการ 0 การเริ่มจาก 1 จึงเป็นกระบวนการทางธรรมชาติที่เราควรปฏิบัติตาม

เมื่อพิจารณาสิ่งนี้แล้วเราจะได้สิ่งนี้:

fun main() {
    println("Give number: ")
    var quantity: Int = readLine()!!.toInt()

    println(sumOfDigits(quantity))
}


fun sumOfDigits(quantity: Int): Int {
    var score = 0
    var digit: Int
    var number: Int = quantity

    if (number < 1) throw ArithmeticException("Give number >0!")

    while (number > 0) {
        digit = number % 10
        score += digit
        number /= 10
    }
    return score
}

นอกจากนี้ยังสามารถปรับปรุงได้

  • ไม่จำเป็นต้องให้ quantity เป็นตัวแปร เราไม่เคยเปลี่ยนค่าของมัน
  • คุณสมบัติ digit ในฟังก์ชัน sumOfDigits นั้นซ้ำซ้อน เนื่องจากเราสามารถกำหนดผลลัพธ์ของ number % 10 ให้กับคะแนนได้โดยตรง
  • หากเราต้องการจริงๆ เราสามารถพยายามจับข้อยกเว้นที่จะเกิดขึ้นหากผู้ใช้ป้อนอักขระที่ไม่ใช่ตัวเลข
fun main() {
    println("Give number: ")
    val userInput: String = readLine() ?: error("Please provide an input") //this exception is thrown when the input is null (due to the Elvis operator `?:`)
    val number: Int

    try{
        number = userInput.toInt()
    }catch (e: NumberFormatException){
        println("A number needs to be provided. Input `$userInput` cannot be read as number")
        return 
        /*this will just close our procedure, we could also just throw our own exception
          instead of hte println, or just leave the normal exception propagate*/
    }

    println(sumOfDigits(number))
}


fun sumOfDigits(quantity: Int): Int {
    var score = 0
    var number: Int = quantity

    if (number < 1) throw ArithmeticException("Give number >0!")

    while (number > 0) {
        score += number % 10
        number /= 10
    }
    return score
}

ในฐานะนักพัฒนา Kotlin ฉันจะเขียนสิ่งนี้แตกต่างไปจากเดิมอย่างสิ้นเชิง และฉันจะไม่แนะนำให้มือใหม่ใช้ Kotlin แบบนี้ แต่ฉันเชื่อว่ายังคงน่าสนใจสำหรับคุณที่รู้ว่าขั้นตอนของคุณสามารถย่อให้เล็กสุดได้อย่างง่ายดาย (หมายเหตุ ไม่สามารถอ่านได้ และจะต้องมีเอกสารที่เหมาะสมหากคุณตัดสินใจเขียนโค้ดด้วยวิธีนี้)

fun main() {
    println("Give number: ")
    //will take an input from the user and throw an exception if the input is null
    val input = readLine() ?: error("No input given")

    //will throw NumberFormatException if the input is not a number. We are ignoring the actual result of the call itself
    input.toInt() 
    
    /*
        will take each char of the string and create a sum with the given selector. Since the given selector is
        the char itself minus 0, it will actually sum each char, in our case, each digit
    */
    val sum = input.sumBy { it - '0'}
    
    println(sum)
}
person Alex.T    schedule 16.12.2020