Исключение Kotlin Try

#kotlin #exception #try-catch

#kotlin #исключение #попытка-перехват

Вопрос:

Я очень начинающий программист Kotlin. Что я делаю не так с кодом try amp; catch? Есть ли проблема с частью try или частью catch?

 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))
}
 

Комментарии:

1. quantity == 0 само по себе недопустимое утверждение

2. Вам понадобится if (quantity == 0) println("Can't be 0!") . Кроме того, второй улов бесполезен, потому что фактический toInt находится за пределами try блока.

Ответ №1:

Есть несколько концепций, которые вы неправильно поняли.

Давайте начнем с разговора об этом:

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

Несколько проблем. Во-первых, assignment это на самом деле a check .

quantity == 0 не изменит его значение quantity , просто проверит, равно ли оно 0. Результат этой проверки (a Boolean ) полностью игнорируется.

Если вы хотите проверить, равно ли quantity значение 0, вам нужно сделать это в if инструкции.

Вторая путаница, которая, я думаю, у вас есть, касается того, что try/catch делает блок. Он пытается выполнить некоторый фрагмент кода, и если этот код завершается с ошибкой (иначе код выдает исключение), перехват может быть использован для снижения риска остановки процедуры. В некоторых случаях можно остановить процедуру, тогда catch используется для записи дополнительной информации в консоль, для переопределения сообщения об исключении или для вызова других фрагментов кода до завершения процесса.

Третья путаница связана с catch блоками. catch (e: Exception) будет перехватывать все возможные исключения (но не все возможные Throwables ). Это означает, что второй catch блок e: ArithmeticException никогда не произойдет, поскольку первый является более общим.

Учитывая это и предполагая, что вы хотите, чтобы процесс фактически останавливался, когда ввод равен 0, тогда все, что вам нужно сделать, это:

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

или

 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)
}