Can I make Kotlin recognise that `java.io.File.lis...
# announcements
m
Can I make Kotlin recognise that
java.io.File.listFiles
returns null sometimes?
s
something like
val files: List<Files>? = java.io.File.listFiles()
?
or
java.io.File.listFiles()?.let { notNullVal -> …}
?
t
How about writing an extension function ?
Copy code
inline fun java.io.File.listFilesOrNull(): List<File>? = listFiles()
This way, both the function name and its signature warns about a potentially
null
return value, and the compile will force you to handle it.
👍 1
Also, the Kotlin stdlib has some utilities for exploring files. Have a look at this : https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/walk.html
s
why inline?
t
The compiler will replace all calls to `listFilesOrNull()' by
listFiles()
, making that extension function almost free. But the
inline
modifier is not required for that solution to work.
m
ok, thanks. I was just wondering whether there is some way to make Kotlin detect that automatically. I guess there are many more functions like this one in Java SDK.
s
the runtime “knows” if the value is null or not, it’s just that you have to tell what to do at compile time. As Sergey wrote you tell Kotlin that the type can be null by declaring it explicitly via
val files: List<Files>? ...
the issue being that the function you’re calling comes from Java and therefore provides no nullability information (which makes it’s return-type the platform-type
List<Files>!
which means “maybe it’s nullable, maybe it’s not”). So you as developer have to tell Kotlin that this function can return null by explicitly declaring its type as nullable (hence the ‘?’ in the type declaration).
t
In order to make Kotlin aware of the nullability of a declaration in Java code, that Java code must use nullability annotations :
@Nullable
,
@NonNull
,
@NotNull
, etc. The Android SDK was updated to include those annotations wherever possible, making it easier to use it with Kotlin. But I don't think that the JDK will adopt those annotations... I don't think Oracle (that distributes the most used JDK implementation) would like to see Kotlin replace Java 😕
m
Isn't there way to specify these things externally? E.g., in TypeScript/Flow you can add types to existing (non-typed) JavaScript modules without touching them, and compiler/IDE will use that info. You just add these type definitions into dependencies and it just works.
a
Yep, it's called external annotations in IDEA: https://www.jetbrains.com/help/idea/external-annotations.html. These annotations are generated by IDEA automatically for the entire JDK. Until recently, they were not taken into account in Kotlin code analysis. But the upcoming 1.3.40 version of the Kotlin plugin will warn you when it's not safe to use such Java methods: https://youtrack.jetbrains.com/issue/KT-24292. Example:
Copy code
import java.io.File

fun foo() {
    val files = java.io.File("snth").listFiles()
    bar(files) // [NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS] Type mismatch
}

fun bar(files: Array<out File>) {
}
Note that it's not a proper Kotlin compiler warning, even though it looks like it. It's only displayed in the IDE editor. You can try the 1.3.40 EAP right now: https://discuss.kotlinlang.org/t/kotlin-1-3-40-early-access-preview/12775
💯 2
m
@Alexey Belkov [JB] thanks! I'll try that.