kotlin - Declaration-site variance may cause ClassCastException -
kotlin introduces declaration-site variance described @ here.
the out/in keywords generic parameters may cause classcastexception in case. program shown below.
fun main(args: array<string>) { var l: list<string> = mutablelistof("string") demo(l) println("======") (s in l) { println(s) } } fun demo(strs: list<string>) { val objects: list<any> = strs // ok, since t out-parameter if (objects mutablelist) { val obs: mutablelist<any> = objects mutablelist<any> obs.add(textview()) } } output:
exception in thread "main" java.lang.classcastexception: com.kotlin.demo.clzz.textview cannot cast java.lang.string @ com.kotlin.demo.clzz.declaration_site_variancekt.main(declaration-site-variance.kt:14) ====== adn is way use out/in keywords recommended practice? , why?
your code can compiled without warnings, because declaration-site variance available in kotlin.
this in contrast java's use-site variance wildcards in type usages make types covariant.
for example 2 soruce interfaces use declaration-site variance in kotlin:
interface source<out t> interface source<in t> both of 2 source interfaces generated same source code in java below:
// v---`t extends object` rather `? extends t` public interface source<t>{ /**/ } this because wildcard ? used type argument rather type parameter in java. t in source<t> type parameter , ? extends string in source<? extends string> type argument.
so if use type projections make objects force list<out any>, compiler reports unchecked_cast warning , example:
fun demo(strs: list<string>) { // v--- makes explicitly using out type proejction val objects: list<out any> = strs if (objects mutablelist) { // v--- unchecked_cast warning reported val obs: mutablelist<any> = objects mutablelist<any> obs.add(textview()) } } in other words, can't assign list<out any> mutablelist<any>. otherwise, compilation error. example:
fun demo(strs: list<string>) { val objects: list<out any> = strs if (objects mutablelist) { // v--- ? extends object //error: can't assign mutablelist<out any> mutable<any> // v ^--- object val obs: mutablelist<any> = objects obs.add(textview()) } } if assign objects mutablelist<out any> variable, you'll found can't adding anything, since can't create nothing in kotlin @ all. example:
fun demo(strs: list<string>) { val objects: list<out any> = strs if (objects mutablelist) { // v--- down-casting `mutablelist<out any>` val obs: mutablelist<out any> = objects // v---error: can't instantiated obs.add(nothing()) } } q: way use out/in keywords recommended practice?
java has described how use wildcard , applies in kotlin.
an "in" variable, note "in" in here ? extends t , same kotlin out variance:
an "in" variable serves data code. imagine copy method 2 arguments:
copy(src, dest). src argument provides data copied, "in" parameter.
an "out" variable, note "out" in here ? super t , same kotlin in variance:
an "out" variable holds data use elsewhere. in copy example,
copy(src, dest), dest argument accepts data, "out" parameter.
Comments
Post a Comment