I am having trouble implementing a method from an ...
# getting-started
m
I am having trouble implementing a method from an interface that was defined in Java. It has a
Class<T>
return type, but I can't seem to make it work with nullable types without triggering a compiler warning
Copy code
override fun toType(): Class<Boolean?> = 
        Boolean::class.java as Class<Boolean?>
This works, but the cast triggers the warning:
Unchecked cast Class<Boolean> to Class<Boolean?>
I tried to qualify it as <out Boolean>, but I can't seem to make it work?
z
are you looking for
Class<Boolean>?
instead?
m
no. the return type needs to be a
Class<T>
I managed to make this work without any warnings:
Copy code
override fun toType(): Class<Boolean?> =
            toTypeReified()

    private inline fun <reified T>toTypeReified(): Class<T> = T::class.java
but I'm not sure it's the best solution
r
There is no
Class<Boolean?>
, so you may need to look at your generics.
z
@Ruckus is correct, there is no
Class<Boolean?>
What is the actual return type of the method from the Java interface? Assuming that Java interface isn't marked with
@Nullable
the return type should be
Class<Boolean>!
So, in this case,
Class<Boolean>
or
Class<Boolean>?
should work.
m
Oh, I hadn't tried with
Boolean
before, since I always use it with Boolean? types 🤪
Can you help me understand why
Class<Boolean?>
doesn't exist , I didn't get any compiler errors?
z
Class<Boolean?>
implies that
Class<Boolean>
and
Class<null>
are valid.
Class<null>
isn't possible.
Class<Boolean>?
implies that null is a valid return value.
Class<null>
doesn't work because
null
is a primitive type and you can't pass primitive types as type parameters to any generic.
m
Got everything else, but not sure I could wrap my head around the
implies that [...] Class<null> is valid
bit. Isn't the T in generics supposed to be the "placeholder of a type"? And isn't
Boolean?
a type?
z
Boolean?
is a type, but there are restrictions on what you can pass to generics as parameters.
And
Class
is even more special
m
Ah ok! Do you know where i can read more on that? i couldn't find these specifics in the documentation
z
m
Thanks for your help 🙂
d
You are running into a platform type. If Java says
Boolean
, Kotlin cannot know if it's nullable or not, so it sees it as a platform type, which adjusts to being nullable or not nullable depending on context. If you are overriding a method, IntelliJ will choose the conservative way and choose nullable. but in this case that's not correct, so if you change the return type to
Class<Boolean>
your code still compiles and makes sense.
m
The interface is
Class<T> toType();
It is applied to my Kotlin class, tho, which has a
Boolean?
type
Well, I tried to present a minimal example but I think I have to explain the whole thing lol I'm using JOOQ's Converter interface to convert a BigDecimal (from the database) to a Boolean (domain type) (it's complicated, but I can't change the database type, it's basically a 0|1 column) The class is
Copy code
class EnabledIndicatorConverter: Converter<BigDecimal, Boolean?> {

    override fun to(isEnabled: Boolean?): BigDecimal? {
        return isEnabled?.let { BigDecimal.ONE } 
                ?: BigDecimal.ZERO
    }

    override fun fromType(): Class<BigDecimal> =
            BigDecimal::class.java

    override fun toType(): Class<Boolean?> =
            Boolean::class.java as Class<Boolean?>

}
d
You can probably do something like this:
Copy code
class EnabledIndicatorConverter: Converter<BigDecimal, Boolean> {

    override fun to(isEnabled: Boolean?): BigDecimal? {
        return isEnabled?.let { BigDecimal.ONE } 
                ?: BigDecimal.ZERO
    }

    override fun fromType(): Class<BigDecimal> =
            BigDecimal::class.java

    override fun toType(): Class<Boolean> =
            Boolean::class.java

}
m
Yeah, that worked!