Kotlin中filterNotNull处理对象属性的编译问题咨询
Great question—this is a common point of confusion with Kotlin's smart casts and collection operations! Let's unpack why the compiler behaves this way and what clean alternatives you can use.
Why the Compiler Doesn't Recognize it.venue as Non-Null After Filtering
When you use events.filterNotNull(), you're filtering out null elements from the list itself. Kotlin's compiler can track that every element in the resulting list is non-null, so accessing .name (a non-null property of the non-null element) is safe.
But when you do events.filter { it.venue != null }, you're filtering based on a nullable property of the list elements, not the elements themselves. Kotlin's smart cast can't carry that property-level non-null guarantee across the filter → map boundary. The compiler still sees it.venue as Venue? in the map block because it can't verify that no other code modified the property between the filter and map operations (even if you know it didn't).
Clean Alternatives for Nullable Properties
Luckily, there are several idiomatic ways to handle this without relying on risky !! assertions:
Use
mapNotNullto extract non-null properties first
This is the most concise and safe approach.mapNotNullwill skip any elements where the lambda returns null, and the resulting list will only contain non-null values:data class Event(val venue: Venue?) data class Venue(val name: String) val events: List<Event> = // your list of events val venueNames: List<String> = events.mapNotNull { it.venue?.name }Or if you need to work with the
Venueobject before getting the name:val venueNames = events.mapNotNull { it.venue }.map { it.name }Filter first, then use safe calls with
let
If you need to keep the filtered list ofEventobjects for other operations, you can combine filtering withletto safely access the non-null property:val filteredEvents = events.filter { it.venue != null } val venueNames = filteredEvents.map { it.venue?.let { venue -> venue.name } }Note this will give you a
List<String?>, so you'd still need to usefilterNotNull()if you want only non-null names.Non-null assertion (use with extreme caution)
If you're 100% certain that everyEventin the filtered list has a non-nullvenue, you can use!!—but this will throw aNullPointerExceptionif your assumption is wrong:val venueNames = events.filter { it.venue != null }.map { it.venue!!.name }
Key Takeaway
There's no direct equivalent to filterNotNull() for nullable properties, but mapNotNull() is the idiomatic Kotlin solution to safely collect non-null property values from a list. It keeps your code concise and avoids the risk of null pointer exceptions.
内容的提问来源于stack exchange,提问作者hughjdavey




