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

Я очень начинающий программист на Kotlin. Что я делаю не так с кодом try & 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))
}

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. Результат этой проверки (Boolean) полностью игнорируется.

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

Второе замешательство, которое, я думаю, у вас есть, касается того, что делает блок try/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? Так как нам не нужны нули, естественно начинать с 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 dev, я бы написал это совсем по-другому, и я бы не советовал новичку так использовать 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