Not sure what is causing this, but i am trying request data from the api and i am getting an IllegalArgumentException
package com.example.tmdb
import com.google.gson.Gson
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
class MainPresenter(private val view:MainView, private val apiRepository: ApiRepository, private val gson: Gson){
fun getMovieList(){
doAsync {
val data = gson.fromJson(apiRepository.doRequest(TMDBApi.getMovie()),
MovieResponse::class.java)
uiThread {
view.showMovieList(data.result)
}
}
}
}
Line in which i am getting exception is
view.showMovieList(data.result)
and
class MainPresenter(private val view:MainView, private val apiRepository: ApiRepository, private val gson: Gson){
Error message showing in Logcat is:-
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter data
at com.example.tmdb.MainActivity.showMovieList(MainActivity.kt)
at com.example.tmdb.MainPresenter$getMovieList$1$1.invoke(MainPresenter.kt:14)
at com.example.tmdb.MainPresenter$getMovieList$1$1.invoke(MainPresenter.kt:7)
at org.jetbrains.anko.AsyncKt$uiThread$1.run(Async.kt:71)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Parameter specified as non-null is null. What this means is that data.result is coming back as null. There could be multiple reasons for that, the most common one I can think of is that the json that is returned from the api call isn't the same object as what you said in MovieResponse::class.java.
Regardless, the error java.lang.IllegalArgumentException: Parameter specified as non-null is null comes up when you tell the compiler that the param passed into this function will never be null but is in fact null
I'm doing a bit of guessing here, but I assume that the following are true:
MovieResponse is defined in Java
showMovieList() is defined in Kotlin and accepts only non-null values
Values coming from Java are treated specially in Kotlin: you're allowed to work with them as though they are non-null, but null values are allowed. This is a language feature that is meant to make your life better, as the alternative is to treat every value that comes from Java as nullable.
You can read more about this here: https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types
What this means for you is that you don't get compile-time null safety, and have to solve the problem yourself. Clearly data.result is null sometimes, so you need to make sure to handle this scenario.
Replace these lines:
uiThread {
view.showMovieList(data.result)
}
with these:
data.result?.let {
uiThread {
view.showMovieList(it)
}
}
Related
I'm new to Kotlin and these two below codes give different results.
fun main() {
var name: String? = "Rajat"
name = null
print(name?.toLowerCase())
}
Output: Compilation Error (illegal access operation)
fun main() {
var name: String? = null
print(name?.toLowerCase())
}
Output: null
When you do this assignment:
name = null
name is smart casted to Nothing?, which is problematic. Nothing is the subtype of every type, and so you become able to call any accessible extension functions of any type, according to the overload resolution rules here.
Compare:
fun main() {
var name: String? = "Denis"
name = null
print(name?.myExtension()) // works
val nothing: Nothing? = null
print(nothing?.myExtension()) // also works
}
fun Int.myExtension(): Nothing = TODO()
Note that allowing you to call any extension function on Nothing is perfectly safe - name is null anyway, so nothing is actually called.
Char.toLowerCase and String.toLowerCase happen to be two of the extension functions that are accessible, and you can call both on name, which is now a Nothing?. Therefore, the call is ambiguous.
Note that smart casts only happens in assignments, not in initialisers like var name: String? = null. Therefore, name is not smart casted to Nothing? in this case:
fun main() {
var name: String? = null
print(name?.toLowerCase()) // better to use lowercase(), toLowerCase is deprecated!
}
For the reason why, see my answer here.
The actual error on your first example is
Overload resolution ambiguity: public inline fun Char.toLowerCase(): Char defined in kotlin.text public inline fun String.toLowerCase(): String defined in kotlin.text
Looks like the Kotlin compiler is being too smart for its own good here. What's happening, is that on the second example, you are explicitly defining a variable of type String? and assigning it some value (null in this case, but that doesn't matter).
On the second example, you are defining a variable of some type, and then telling the compiler "hey, after this assignment, name is always null". So then it remembers the more-specific "name is null" instead of "name is String?".
The standard library has two methods called toLowerCase, one on Char and one on String. Both of them are valid matches now, and the compiler is telling you it doesn't know which one to pick. In the end that won't matter, because name is null, but the compiler apparently doesn't use that final thing to throw out the method call altogether.
My function:
fun func(vararg objects: Any?) {
}
When I call func(null), got Exception: Caused by: java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter objects.
And I saw decompile java code is this:
public static final void func(#NotNull Object... objects) {
Intrinsics.checkNotNullParameter(objects, "objects");
printer.v(new Object[]{objects});
}
Is there any way to solve this?
You can't have a null in a vararg in kotlin, this post on kotlinlang
confirms it.
Note that vararg parameters are, as a rule, never nullable, because in
Java there is no good way to distinguish between passing null as the
entire vararg array versus passing null as a single element of a
non-null vararg array.
fun main() {
val set: Set<Int>?
set = null
val emptySet: Set<Int> = set.orEmpty()
}
Can't figure out why even when explicitly typing the set variable as Set <Int>? the compiler considers that in the extension method set.orEmpty () set - is a string and, accordingly, crashes with an error:
Kotlin: Type mismatch: inferred type is String but Set was expected
But when declaring and initializing in one line, everything happens correctly:
fun main() {
val set: Set<Int>? = null
val emptySet: Set<Int> = set.orEmpty()
}
The behavior you're observing can be explained by the interaction of two Kotlin features:
first, the type of set variable is narrowed to Nothing? as a result of a smart cast after the assignment of null value to it. The smart cast after an assignment can be useful in cases when it narrows variable type to a more specific type, but narrowing to Nothing? does more harm than good.
second, among all overloads of orEmpty function available for a value of type Nothing?, the non-generic one String?.orEmpty() is chosen due to the specific rule of Kotlin overload resolution: a non-generic candidate is preferred to generic ones.
This behavior indeed can be puzzling, so I've reported this problem as KT-50661.
I think this is related to the fact that the compiler is not so smart that it could deduce that the code set = null will be executed exactly once – it could be zero times or more than once.
If you know that it will run exactly one, you can tell the compiler by using a feature called kotlin.contracts:
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
#ExperimentalContracts
fun main() {
val set: Set<Int>?
once { set = null }
val emptySet: Set<Int> = set.orEmpty()
}
#ExperimentalContracts
fun once(lambda: () -> Unit) {
contract { callsInPlace(lambda, InvocationKind.EXACTLY_ONCE) }
lambda()
}
See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.contracts/
In a quarkus/kotlin app, I have a rest client that is very basic:
#Path("/my/api/v1")
#RestClient
interface MyApiClient { }
Problem is, when a request fails, it returns a response that fails to be mapped. So I want to add an exception mapper, in order to log the real error:
class MyExceptionMapper : ResponseExceptionMapper<java.lang.RuntimeException?> {
override fun toThrowable(r: Response): java.lang.RuntimeException {
Logger.getLogger(MyApiClient::class.java).error(r.status)
return RuntimeException("failed")
}
}
To do so, I should annoate my client with:
#RegisterProvider(MyExceptionMapper::class.java)
Doing so, I have a kotlin error:
An annotation argument must be a compile-time constant
I googled but could find solutions only for strings. In this case, kotlin expects the java class to be a compile time constant. How to get it?
Should work with simple:
#RegisterProvider(MyExceptionMapper::class)
Look at the following code running in Kotlin REPL:
>>> null.takeIf({1==2})
res4: kotlin.Nothing? = null
Why this don't cause NullPointerException?
You code doesn't cause NullPointerException because takeIf is an extension function.
Extension functions are translated into method receiver, first argument being the object you invoked your function on.
So instead of null.takeIf { false } (simplifying your example), you could wonder why the following function doesn't throw a NullPointerException:
fun <T> takeIf(me: T, predicate: (T) -> Boolean): T? {
...
}
Well, for that we need to look into takeIf() implementation (removing annotations and contract):
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
return if (predicate(this)) this else null
}
So, in case your predicate is false (as in your example, 1==2), it just short-circuits and returns null.
What if it's true, then? Will we finally get a NullPointer?
Nope:
val nothing: Nothing? = null.takeIf {
true
}
Kotlin design approach for types aims to eliminate NPEs on purpose. Conditions that might trigger one are limited to, as seen on the docs:
An explicit call to throw NullPointerException();
Usage of the !! operator that is described below;
Some data inconsistency with regard to initialization, such as when:
An uninitialized this available in a constructor is passed and used somewhere ("leaking this");
A superclass constructor calls an open member whose implementation in the derived class uses uninitialized state;
Java interoperation:
Attempts to access a member on a null reference of a platform type;
Generic types used for Java interoperation with incorrect nullability, e.g. a piece of Java code might add null into a Kotlin MutableList, meaning that MutableList should be used for working with it;
Other issues caused by external Java code.
The third option is for NPE-lovers: the not-null assertion operator
(!!) converts any value to a non-null type and throws an exception if
the value is null. We can write b!!, and this will return a non-null
value of b (e.g., a String in our example) or throw an NPE if b is
null:
val l = b!!.length
Thus, if you want an NPE, you can have it, but you
have to ask for it explicitly, and it does not appear out of the blue.
So your code is behaving as expected. See the link for more info
https://kotlinlang.org/docs/reference/null-safety.html