David Kubecka
03/09/2023, 11:56 AM@Nullable
which is overly pessimistic?
For example, I want to create a shortcut for transactions execution:
fun <T> PlatformTransactionManager.execute(block: () -> T): T =
TransactionTemplate(this).execute { _ -> block() }
This doesn't compile because execute
is marked as @Nullable
, therefore the return type must be T?
. Instead would like it to be T
, that is whatever block
returns (which might also be null).Rob Elliot
03/09/2023, 11:59 AMfun <T> PlatformTransactionManager.execute(block: () -> T): T =
TransactionTemplate(this).execute { _ -> block() } ?: throw IllegalStateException("Expected it to be impossible for execute to return null")
David Kubecka
03/09/2023, 12:00 PMRob Elliot
03/09/2023, 12:00 PMRiccardo Lippolis
03/09/2023, 12:09 PMfun <T> PlatformTransactionManager.execute(block: () -> T): T =
TransactionTemplate(this).execute { _ -> block() } as T
this appears to be working, and it removes the warningDavid Kubecka
03/09/2023, 12:13 PMRiccardo Lippolis
03/09/2023, 12:17 PMephemient
03/09/2023, 12:24 PMas T
,
@Suppress("UNCHECKED_CAST")
Riccardo Lippolis
03/09/2023, 12:31 PMDavid Kubecka
03/09/2023, 12:37 PMkqr
03/09/2023, 12:39 PMT
?David Kubecka
03/09/2023, 12:40 PM<T>
doesn't say anything about its nullability (in contrast to e.g. <T : Any>
)kqr
03/09/2023, 12:45 PMDavid Kubecka
03/09/2023, 12:46 PMT
and T?
. Well, T
in this case means the exact return type of the block (preserving nullability), while T?
might not preserve the nullability, i.e. even if block
returned non-null then TransactionTemplate#execute
might still return null.
I guess that's a principal deficiency of those java annotations.Riccardo Lippolis
03/09/2023, 1:44 PMWeird indeed. Does it compile without warnings? (btw I also use IDEA)yes, no compiler warnings as well... I use Kotlin 1.8.10, btw
deive
03/09/2023, 5:04 PM!!
?
fun <T> PlatformTransactionManager.execute(block: () -> T): T =
TransactionTemplate(this).execute { _ -> block() }!!
Rob Elliot
03/09/2023, 5:05 PMdeive
03/09/2023, 5:07 PMTransactionTemplate.execute
returns T? but you are always running block: () -> T
then TransactionTemplate(this).execute { _ -> block() }!!
should be OK?Rob Elliot
03/09/2023, 5:08 PMval x: String = tm.execute { "not null" }
val y: String? = tm.execute { if (Random.nextInt(2) == 1) "not null" else null }
ephemient
03/09/2023, 5:09 PM<T>
is neither nullable nor non-nullable) and Kotlin (where there is such a distinction)@Nullable <T> T foo()
becomes Kotlin fun <T> foo(): T?
, Java @NonNull <T> T foo()
becomes Kotlin fun <T> foo(): T & Any
, and <T> T foo()
can't be written directly in Kotlin due to platform nullability. none of them result in fun <T> foo(): T
deive
03/09/2023, 5:25 PMblock
returns (which might also be null)." - this means that block will have to return T?
so what I said was moot!Rob Elliot
03/09/2023, 5:26 PMT
. Whether or not `T`'s concrete type is nullable depends on how you define the block.val notNullBlock: () -> String = { "not null" }
val x: String = tm.execute(notNullBlock)
val nullableBlock: () -> String? = { if (Random.nextInt(2) == 1) "not null" else null }
val y: String? = tm.execute(nullableBlock)
deive
03/09/2023, 5:30 PMPlatformTransactionManager.execute
to be fun <T : Any>
for a non-nullable version?Rob Elliot
03/09/2023, 5:30 PMdeive
03/09/2023, 5:30 PMRob Elliot
03/09/2023, 5:32 PM