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