Throw custom exception when item not found in a Kotlin collection - kotlin

I want to find a person from a list, or throw a PersonNotFoundException otherwise.
The first() function from kotlin.collections throws NoSuchElementException in this scenario, but I want to throw my custom exception i.e. PersonNotFoundException.
Currently I'm using the following logic:
val persons: List<Person> = listOf(...)
val name: String = "Bob"
persons.firstOrNull {
it.name == name
}.let {
it ?: throw PersonNotFoundException("No person was found with name $name")
}
But I'm not quite satisfied with it.
It feels that there is some existing function for this use case that I'm not aware of.
Can anyone help me improve it?

You don't even need let. All let does is it lets you refer to the found thing using it.
The code can be shortened to the more idiomatic:
persons.firstOrNull {
it.name == name
} ?: throw PersonNotFoundException("No person was found with name $name")

Related

Get nullable property or throw exception

I recently switch from java to kotlin. I have following method in my code and I would like to ask if there is better way how to write it in kotlin?
This is my parsing method which parse id from object obj which has nullable property nullableNestedObject and this object had id property.
fun parseId(obj: WrappingObject): Long {
val myId = obj.nullableNestedObject?.myId
if (myId === null) {
logger.error("Id not found because of ...")
throw InternalException("Id not found")
}
return myId
}
You can simplify it a bit by putting the relevant code into a run() call:
fun parseId(obj: WrappingObject): Long
= obj.nullableNestedObject?.myId
?: run {
logger.error("ID not found because of...")
throw InternalException("ID not found")
}
Run is a scoping function that provides a simple way to group lines of code into a block.
(If the block didn't throw an exception, it would have to return a Long value too, of course.)
You'll notice I've made it into a single-expression function — it's shorter, and easier to see what it returns. (That's only appropriate for fairly short functions, though.)
(I've also capitalised ‘ID’, which is a bugbear of mine: it's an abbreviation, and pronounced as two letters, so both should be capitalised. Otherwise, it looks just like the term from psychoanalysis…)
Another change you might consider is to make it an extension function on WrappingObject:
fun WrappingObject.parseId(): Long
= nullableNestedObject?.myId
?: run {
logger.error("ID not found because of...")
throw InternalException("ID not found")
}
That way, it can be called as myWrappingObject.parseId(), just as if it were a method of WrappingObject. That can keep the namespace a little clearer, and lets your IDE suggest it.
As per Tulip's answer, this would be even simpler if you didn't need to call the logger as well:
fun parseId(obj: WrappingObject): Long
= obj.nullableNestedObject?.myId
?: throw InternalException("ID not found")
When I write custom exceptions, I tend to write a log entry in the constructor, which enables that sort of simplicity as well as avoiding duplication of the log calls.
If your Long value can be nullable, you can use this way, and check null or not null later
fun parseId(obj: WrappingObject): Long? {
return obj.nullableNestedObject?.myId
}
If you are looking for concise (i.e. minimal) code, I suggest using the elvis operator (?:) and the run scope function:
fun parseId(obj: WrappingObject): Long = obj.nullableNestedObject?.myId ?: run {
logger.error("Id not found because of ...")
throw InternalException("Id not found")
}
Just another variation on the same theme, just because I find scoping functions and brackets sometimes make the code less simple
fun WrappingObject.parseId() = nullableNestedObject?.myId ?: logAndThrow()
private fun logAndThrow() : Nothing {
logger.error("ID not found because of...")
throw InternalException("ID not found")
}

Non nullable field of object created via reflection is null

I have next class structure:
class ExampleResponse(
#SerializedName("status")
val status: String
)
I am creating instance of this class via reflection:
fun convert(typeAdapterFactory: TypeAdapterFactory, gson: Gson): Optional<*> {
return try {
val genericTypeClassName = "com.example.package.ExampleResponse"
val genericClass = Class.forName(genericTypeClassName)
val genericTypeAdapter = gson.getDelegateAdapter(typeAdapterFactory, TypeToken.get(genericClass))
val response = genericTypeAdapter.fromJson("{}")
Optional.of(response)
} catch (e: Exception) {
Optional.empty<Any>()
}
}
I am waiting that on the line genericTypeAdapter.fromJson("{}") it will throw exception, because status will be null. But I am receiving instance of ExampleResponse with null status field.
I want to return Optional.empty() if status is null. How can I achieve this without checking fields? (checking field to non null is not acceptable because the real function is universal and I won't know what class I'll receive here).
Gson doesn't know when a field can/cannot be null, since it's a Java library and Java knows nothing about nullability.
This question and answers suggests some workarounds:
Gson optional and required fields

Generic method for finding instances of classes with 'is' operator

I'm new to Kotlin development and trying to create a function that takes an instance of a Exception and a class (e.g RuntimeException) to check if the instance is an instance of the specific class, in Kotlin. The idea is that you have caught a specific type of exception. You then want to traverse up the causes of this exception until you have the specific exception that you were looking for.
fun findExceptionType(currentException : Throwable?, exceptionToFind: KClass<Throwable>): Throwable? {
var _currentException = currentException
while((_currentException!!.cause == null)!!) {
if (_currentException is exceptionToFind) {
return _currentException.cause
}
_currentException = _currentException.cause
}
return null
}
The idea is that it will keep traversing up the exception.cause until either the exception.cause is null, or you have found the type of exception that you were searching for. This seems like something that would already have been implemented and so I'm surprised I'm having to implement this myself.
The reason for this utility function is to avoid having to traverse up all the exception.causes until you find the specific type that you need.
To be more specific:
In Kotlin there is an 'is' operator, for instance you can say if (s is String), however in my function above I want to make it generic by having something like if (s is X) where X is passed into the function. What would be the type of X? At the moment I've used KClass but I'm not sure what the type signature of the is operator is?
I agree with #dyukha. It's pretty convenient to use reified type parameters here. With it you can rewrite your function like:
inline fun <reified T : Throwable> findExceptionType(throwable: Throwable?): T? {
var error = throwable
while (error !is T) {
error = error?.cause
}
return error
}
As generic if (s is X) where X is passed into the function you can use something like this:
(x as? String)?.let { println(it) }

Is there an elegant kotlin way of convincing the compiler that a nullable field to which I just assigned a real value can't be null anymore?

I have read that using !! should generally be avoided.
Is there a way to write the following code in a more elegant way without having to add something like obsolete null checks and duplicated or dead blocks of code?
class A(var field: Thing?) {
fun getField(): Thing {
if (field == null) {
field = Thing()
}
return field!!
}
}
Also I don't understand why the compiler requires the !!-'pray-this-isn't-null-operator' to be satisfied in this scenario.
EDIT: Consider that it is important to me that a potential solution uses lazy initialization if the field is null!
Problem
As Enzokie already mentioned in the comments, another thread could have changed field after the null check. The compiler has no way of knowing that, so you have to tell it.
class A(var field: Thing?) {
fun getField(): Thing {
if (field == null) {
field = Thing()
}
// another thread could have assigned null to field
return field!! // tell the compiler: I am sure that did not happen
}
}
Solution (Eager)
In you particular case it would be a good idea to use a parameter f (you could name it "field" too, but I avoided that for clarity) in the constructor (without val/var) and afterwards assign it to a property field to which you assign either f or a new instance of Thing.
This can be expressed really concise with the Elvis operator :? which takes the left hand side if not null and the right hand side of the expression otherwise. So, in the end field will be of type Thing.
class A(f: Thing?) {
val field = f ?: Thing() // inferred type Thing
}
Solution (Lazy)
Since it was mentioned by gidds, if you need to initialize field lazyly you could do it like this using delegated properties:
class A(f: Thing?) {
val field by lazy {
f ?: Thing() // inferred type Thing
}
}
The call site does not change:
val a = A(null) // field won't be initialized after this line...
a.field // ... but after this
How about this?
class A(field: Thing?) {
private lateinit var field: Thing
init {
field?.let { this.field = it }
}
fun getField(): Thing {
if (!this::field.isInitialized) {
field = Thing()
}
return field
}
}
When you define a field, you actually define a variable plus two accessor methods:
val counter: Integer = 0
It is possible to customize the accessor methods by writing this instead:
val n = 0
val counter: Integer
get() = n++
This will execute the n++ each time you access the counter field, which therefore returns different values on each access. It is uncommon and unexpected but technically possible.
Therefore the Kotlin compiler cannot assume that two accesses to the same field return the same value twice. Usually they do, but it is not guaranteed.
To work around this, you can read the field once by copying it into a local variable:
fun count() {
val counter = counter
println("The counter is $counter, and it is still $counter.")
}

Kotlin: check if a nullable value is valid in an if statement

Ideally, I think the commented-out if statements make more sense, at least to me. I mean, if someone asks me if null is bigger than 0, than I would answer no. Or if null is true, then also no. But those did not work as I expected, and throw compilation errors. So, I have changed those like below. But those do not look good or concise. Is there a better way to handle these?
class Result(val code:Int)
{
}
fun getResult():Result?
{
return null;
}
fun main(args: Array<String>)
{
var result = getResult();
var success:Boolean? = null;
//if(result?.code > 0)
if(result?.code?:0 > 0)
{
print("Good.");
}
//if(success)
if(success == true)
{
print("Good.");
}
}
The > is compiled to a call of compareTo(other: Int), which works by convention (its defined as an operator on Int). You cannot invoke this function on nullable Int? though.
There'd be a workaround: Create another extension on Int?:
operator fun Int?.compareTo(other: Int): Int =
(this ?: 0).compareTo(other)
Now your call does work:
if (result?.code > 0)
print("Good.")
the nullable element is actually the Result instance itself, not its code property.
i think using let in combination with the safe-get operator on the result more accurately reflects the design of the code:
result?.let {
if(it.code > 0) {
}
}
The reason the commented-out code did not compile is because result?.code is nullable and you can't call comparing operator (i.e > in this case) on a nullable expression because they don't type match. (it is defined to only accept non-nullable types)
if null is bigger than 0, than I would answer no. Or if null is true, then also no
Kotlin completely disambiguates between nullable and non-nullable entity. So, at compile time kotlin compiler refuses to compile if you are comparing something with a nullable type, to avoid run time exception ahead of time. In java,
Integer x = null;
System.out.println(x > `)
this compiles but throws a NullPointerException on runtime, which you obviously do not want. Kotlin compiler is just being smart here to avoid such runtime exceptions by refusing to compile.
Now onto the better way to deal with it, like everyone said, using let is an appropriate way. A simpler way can be a regular null check with if expresion
if(result != null && result.code > 0) {
print("Good.");
}
result?.code > 0
It's not working because > internally calls compareTo() method. compareTo() method does not work on a nullable object. That's why you have to add elvis operator(?:) on variable code to assign a value if the code variable is null. So that the value is not null and then compareTo() method works.
result?.code?:0 > 0
I have added a let to solve. If the result is not null then we will execute the code within the let block. Please check the updated code.
class Result(val code:Int){
}
fun getResult():Result?{
return null;
}
fun main(args: Array<String>){
var result = getResult();
var success:Boolean? = null;
//if(result?.code > 0)
if(result?.code?:0 > 0){
print("Good.");
}
// Updated Code
result?.let{
if(result.code > 0)
print("Good.")
}
//if(success)
if(success == true){
print("Good.");
}
}