Kotlin - выполнить оператор и замаскировать исходное исключение, выданное оператором - PullRequest
0 голосов
/ 07 октября 2019

Проблема

Я использую Java Reflection API для создания нового экземпляра класса Data:

val targetObject = Class.forName(sourceObject.javaClass.name).getConstructor().newInstance()

Копилер никогда не жалуется на newInstance()исключение. Но при создании нового экземпляра класса Data он, естественно, создает исключение NoSuchMethodException: <init> [], поскольку класс Data не имеет неявного конструктора с нулевым аргументом, если только не присвоены начальные значения или не добавлен конструктор с нулевым аргументом.

Эта реализация является частью библиотеки, и я хочу сообщить разработчику, что происходит не так, и что нужно сделать, чтобы решить проблему, «переопределив» NoSuchMethodException с помощью собственного тела, иначе разработчик не поймет, как решить проблему. Например, уведомление разработчика о том, что класс Data должен иметь либо конструктор с нулевым аргументом, либо значения по умолчанию.

Решение

В настоящее время я передаю объект sourceObjectв метод и возвращаем новый экземпляр или ноль, затем с помощью оператора Элвиса я «переопределяю» исходное исключение:

val targetObject  = newIntanceOrNull(sourceObject) ?: throw NoSuchMethodException("Custom message")


// Rest of the code

fun newIntanceOrNull(sourceObject: Any): Any? = try {
    Class.forName(sourceObject.javaClass.name).getConstructor().newInstance()
} catch (e: NoSuchMethodException) {
    null
}

Что я ищу

A встроенный оператор (или функция), аналогичный оператору Элвиса, но для исключений. Скажем, с левой стороны оператора происходит сбой из-за исключения, тогда должна выполняться правая сторона.

Ответы [ 2 ]

1 голос
/ 07 октября 2019

Использование Результат из стандартной библиотеки Kotlin:

runCatching { /*your code*/ }.getOrNull()
1 голос
/ 07 октября 2019

Я ничего не знаю о такой встроенной функции в Kotlin. Я думаю, что в стандартной библиотеке Kotlin такой функции нет, но вы можете написать ее самостоятельно. Я написал пример этого. Это просто оболочка поверх try-catch, но в некоторых случаях она может быть более читабельной, я думаю:

inline infix fun <T> Function0<T>.orDo(recovery: (Throwable) -> T): T = try {
    invoke()
} catch (e: Throwable) {
    recovery(e)
}

fun error(): String = throw RuntimeException()

fun success(): String = "test"

fun main() {
    val val1 = { success() } orDo { throw RuntimeException("test", it) }
    println(val1) // prints "test"
    val val2 = { error() } orDo { throw RuntimeException("test", it) } // fails with exception
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...