Required <Object> and found <Object>? - kotlin

class TaskRepo(taskData: TaskData) {
companion object {
private val repoByTask: LRUMap<String, OrderFormRepo> = LRUMap(2, 10);
fun getInstance(taskData: TaskData): OrderFormRepo {
if (notFoundObject(taskData.taskId)) {
repoByTask[taskData.taskId] = OrderFormRepo(taskData);
}
return repoByTask[taskData.taskId];//PROBLEM HERE
}
private fun notFoundObject(taskId: String): Boolean {
if (repoByTask.containsKey(taskId) && repoByTask[taskId] != null) {
return false
}
return true
}
}
}
in getInstance method of companion object I am getting compile time error:
Required TaskRepo and found TaskRepo?

LRUMap implements the Map interface, the get method of which in Kotlin returns a V?, as it returns null when no element is present for the given key.
As you've already done the checking beforehand in this case, you can be reasonably sure (assuming no other threads are modifying the map at the same time) that this value won't be null, and force a conversion to the non-nullable type with the !! operator:
return repoByTask[taskData.taskId]!!
For other ways to handle a missing key when reading from a Map, see the getOrDefault and getOrElse methods.

Related

Kotlin function return with any one return type from two different data type without specifying Any as a return type?

I want to allow any one of these two return type (ApiResponse || ErrorResponse). But Return Type should not be a object or Any.
fun getAllUser() : Any? {
val flag = true
return if(flag){
ApiResponse(true)
} else {
ErrorResponse(500)
}
}
With return type (Any), Not able to write an extension function to do specific action with with two different return type. I want t specify Two responses.
In My case, I want to write different Extension function for ApiResponse & ErrorResponse class.
Is it possible to return either ErrorResponse or ApiResponse in a same function?
Create a sealed interface that both of your classes implement:
sealed interface Response<out T>
data class ApiResponse<T>(val data: T): Response<T>
data class ErrorResponse(val errorCode: Int): Response<Nothing>
fun getAllUser() : Response<Boolean> {
val flag = true
return if(flag){
ApiResponse(true)
} else {
ErrorResponse(500)
}
}
Then you can write extension functions that handle either type:
fun Response<Boolean>.foo() {
when (this) {
is ApiResponse<Boolean> -> { TODO() }
is ErrorResponse -> { TODO() }
}
}
Inside the branches of this when statement, the input will be smart cast to the appropriate type.
I got a Idea to return either ErrorResponse or ApiResponse in a same function.
By using [Λrrow][1] library I'm able to achieve this like the following function.
fun getAllUser() : Either<ErrorResponse,ApiResponse>? {
val flag = true
ResponseEntity(ErrorResponse(500),HttpStatus.INTERNAL_SERVER_ERROR)
ResponseEntity.internalServerError().build<ErrorResponse>()
val response: Either<ErrorResponse,ApiResponse> = return if(flag){
Either.right(ApiResponse(true))
} else {
Either.left(ErrorResponse(500))
}
return response
}
I suggest using Result class. Either the one provided by Kotlin or, even better, your own implementation. Here is one of the examples of using custom implementation, along with the explanation. This should give you all the information you need.

kotlin: If value is null then exit, else use that value as not nullable

Essentially this is in the title. I have a value that could be null. If it is, I just want to exit with a message. If it's not null, then there's a whole slew of work I need to do with this value.
I've found similar, but not quite this exact situation. And it's the subtle difference that's driving me nuts. Here is my code in java:
if (value == null) {
print("error!");
return;
}
print(value);
doFunStuff(value);
etc(value);
All those methods using value require it to be non-null.
But I'm having a difficult time figuring this out in kotlin. With everything I try, the compiler still insists that value is still nullable and refuses to use it in the functions.
What is the kotlin way of doing this very common code flow?
If your methods truly have non-null parameters, the Kotlin compiler should be smart enough to do a smart cast to Object from Object?.
fun yourMethod(value: Object?) {
if (value == null) {
print("error!")
return
}
print(value) // Smart cast happens here
doFunStuff(value)
etc(value)
}
fun print(value: Object) {
// Implementation
}
fun doFunStuff(value: Object) {
// Implementation
}
fun etc(value: Object) {
// Implementation
}
But you can also force the conversion by using the !! operator (though in this case the compiler will tell you it's not necessary):
fun yourMethod(value: Object?) {
if (value == null) {
print("error!")
return
}
val nonNullValue = value!!
print(nonNullValue)
doFunStuff(nonNullValue)
etc(nonNullValue)
}
fun print(value: Object) {
// Implementation
}
fun doFunStuff(value: Object) {
// Implementation
}
fun etc(value: Object) {
// Implementation
}
If your value is a local variable or a function parameter, you won't have this problem, because the compiler will smart-cast it to not-null.
So, I'm assuming value in this case is a member property.
Option 1 is to copy it to a local variable to use in the function:
val value = value
if (value == null) {
print("error!")
return
}
print(value)
doFunStuff(value)
etc(value)
Option 2 is to use the let or also scope functions to do the same thing, but this might not be a good option here because so much code would become nested. This is more useful when you're only calling one or two functions with the object, in which case, you wouldn't even have to name it (just call it it).
value.let { value ->
if (value == null) {
print("error!")
return
}
print(value)
doFunStuff(value)
etc(value)
}
If your entire function works with this one property, you can avoid the nesting problem like this, if you don't mind it returning something besides Unit:
fun foo() = value.also { value ->
if (value == null) {
print("error!")
return
}
print(value)
doFunStuff(value)
etc(value)
}
Option 3 is to assert non-null every time you use it, but this is very ugly. This is only safe if you know the property is only ever accessed from the same thread this function is ever called on.
if (value == null) {
print("error!")
return
}
print(value!!)
doFunStuff(value!!)
etc(value!!)
Expanding on #Mehul's answer, this would only run the code in the let if the value was not null. If null, you could run the outside process and return from it.
value?.let { nonNullValue ->
print(nonNullValue);
doFunStuff(nonNullValue);
etc(nonNullValue);
}?: run { print("error!") ; return }
That said, since you are no longer needing the return to abort the function if null, you could simply do this and further clean it up replacing the lambda.
value?.let {
print(it);
doFunStuff(it);
etc(it);
}?: print("error!")
Well, have you already tried something like this and this is not what you expect?
value?.let { nonNullValue ->
print(nonNullValue);
doFunStuff(nonNullValue);
etc(nonNullValue);
}
basically the code inside let block will run only if the value isn't null.

Retain smartcast when creating custom extension

I currently have to write
val myList: List<Int>? = listOf()
if(!myList.isNullOrEmpty()){
// myList manipulations
}
Which smartcasts myList to no non null. The below do not give any smartcast:
if(!myList.orEmpty().isNotEmpty()){
// Compiler thinks myList can be null here
// But this is not what I want either, I want the extension fun below
}
if(myList.isNotEmptyExtension()){
// Compiler thinks myList can be null here
}
private fun <T> Collection<T>?.isNotEmptyExtension() : Boolean {
return !this.isNullOrEmpty()
}
Is there a way to get smartCasts for custom extensions?
This is solved by contracts introduced in Kotlin 1.3.
Contracts are a way to inform the compiler certain properties of your function, so that it can perform some static analysis, in this case enable smart casts.
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
#ExperimentalContracts
private fun <T> Collection<T>?.isNotEmptyExtension() : Boolean {
contract {
returns(true) implies (this#isNotEmptyExtension != null)
}
return !this.isNullOrEmpty()
}
You can refer to the source of isNullOrEmpty and see a similar contract.
contract {
returns(false) implies (this#isNullOrEmpty != null)
}

Kotlin 1.3.11 has broken null-safety?

fun handle() : String {
null?.let { return "Ololo"}
}
val result = handle()
result.trim() // kotlin.TypeCastException: null cannot be cast to non-null type kotlin.CharSequence
Any ideas why null-safe Kotlin function return null?
It's a bug caused by introducing contracts for the standard functions let, run, apply, also in Kotlin 1.3.
The fix is targeted to the version 1.3.20. See KT-28061 for details.
It looks like the Kotlin compiler is adding in a null return in case let doesn't execute. This is probably a bug, since it shouldn't compile, and doesn't in previous versions of Kotlin.
If we just compile your example, we get this:
#NotNull
public final String handle() {
return null;
}
I think that's just a compiler optimization, since null?.let() will never execute.
Using an actual variable yields:
#NotNull
public final String handle() {
return someNullableVariable != null ? "Ololo" : null;
}
In other words, let() doesn't execute if its reference is null. However, since this function needs to return something, the compiler just tells it to return null, since there's nothing else it could return.
Since the function is marked #NotNull, Kotlin will perform a null-check on anything referencing the function:
fun someOtherMethod() {
handle().trim()
}
Becomes
public final void someOtherMethod() {
String handle = handle();
if (handle != null) {
StringsKt__StringsKt.trim(handle).toString();
return;
}
throw new Exception("null cannot be cast to non-null type kotlin.CharSequence");
}
There are two ways to handle this. You could change the return type on handle() to String?:
fun handle(): String? {
someNullableVariable?.let { return "Ololo" }
}
Or you could return something else in case the variable is null:
fun handle(): String {
someNullableVariable?.let { return "Ololo" }
return "someNullableVariable was null"
}
It has to be a bug, because:
a return statement (or better: expression) is missing, since the lambda passed to let won't be invoked
a function with String as return type should never return null.
Interestingly, in Kotlin 1.2.x this does not even compile:
fun handle() : String {
null?.let { return "Ololo"}
}
Error:(6, 0) A 'return' expression required in a function with a block body ('{...}')
In Kotlin 1.3.11 it does.
In any case:
let won't be invoked, because the safe-call operator ? evaluates to null (in this case).

Kotlin: Check if lazy val has been initialised

Is there a way to tell if a lazy val has been initialised in Kotlin without initialising it in the process?
eg if I have a lazy val, querying if it is null would instantiate it
val messageBroker: MessageBroker by lazy { MessageBroker() }
if (messageBroker == null) {
// oops
}
I could potentially use a second variable, but that seems messy.
private var isMessageBrokerInstantiated: Boolean = false
val messageBroker: MessageBroker by lazy {
isMessageBrokerInstantiated = true
MessageBroker()
}
...
if (!isMessageBrokerInstantiated) {
// use case
}
Is there some sexy way of determining this, like if (Lazy(messageBroker).isInstantiated())?
Related (but not the same): How to check if a "lateinit" variable has been initialized?
There is a way, but you have to access the delegate object which is returned by lazy {}:
val messageBrokerDelegate = lazy { MessageBroker() }
val messageBroker by messageBrokerDelegate
if(messageBrokerDelegate.isInitialized())
...
isInitialized is a public method on interface Lazy<T>, here are the docs.
Since Kotlin 1.1, you can access a property delegate directly using .getDelegate().
You can write an extension property for a property reference that checks that it has a Lazy delegate that has already been initialized:
/**
* Returns true if a lazy property reference has been initialized, or if the property is not lazy.
*/
val KProperty0<*>.isLazyInitialized: Boolean
get() {
if (this !is Lazy<*>) return true
// Prevent IllegalAccessException from JVM access check on private properties.
val originalAccessLevel = isAccessible
isAccessible = true
val isLazyInitialized = (getDelegate() as Lazy<*>).isInitialized()
// Reset access level.
isAccessible = originalAccessLevel
return isLazyInitialized
}
Then at the use site:
val messageBroker: MessageBroker by lazy { MessageBroker() }
if (this::messageBroker.isLazyInitialized) {
// ... do stuff here
}
This solution requires kotlin-reflect to be on the classpath. With Gradle, use compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
The isAccessible = true part is required for the .getDelegate(), because otherwise it cannot access the private field storing the delegate reference.
Testing if the lazy property is easy enough:
import kotlin.reflect.KProperty0
import kotlin.reflect.jvm.isAccessible
val KProperty0<*>.isLazyInitialized: Boolean
get() {
// Prevent IllegalAccessException from JVM access check
isAccessible = true
return (getDelegate() as Lazy<*>).isInitialized()
}
…but you can make it even easier to reference a property without initializing it:
/**
* Returns the value of the given lazy property if initialized, null
* otherwise.
*/
val <T> KProperty0<T>.orNull: T?
get() = if (isLazyInitialized) get() else null
Now you can do things like:
private val myList by lazy {
mutableSetOf<String>()
}
fun add(str: String) {
// Create the list if necessary
myList += str
}
fun remove(str: String) {
// Don't create the list
::myList.orNull?.remove(str)
}
fun clear() {
// Don't create the list
::myList.orNull?.clear()
}