Nullable upper bound


#1

I was wondering if somebody could explain this to me, something I'm not understanding.

 
public class Foo<T> {

  public var bar: T? = null

This will provide the warning: T has a nullable upper bound. This means that a value of this type may be null. Using T? is likely to mislead the reader.

Is this because the parameterized type T could potentially be a nullable type? Such as Foo<String?>, which would make bar: T? redundant?

How would you write the following without warnings?  (suppressing the warning doesn’t count)

public class Foo<T> {
     public var items: Array<T?> = arrayOfNulls(16)

#2

If you expect the type argument used to substitute T to be always non-null, like game objects or something, you can use type parameter constraints to specify it like this:

public class Foo<T : Any> {

#3

It'd be nice if this warning had clearer wording. I encountered it yesterday and found it very confusing *despite* having already seen this thread! I had to come back to it for a reminder on what it was talking about and what the solution might be. I do not have any suggestions though.


#4

I had a similar question. Let's say I have a generic class that I'd like to allow both nullable and non-nullable types. However, one of the methods I'd like to allow for a return type that could be null, regardless of the generic used. Something like this:

  trait Test<K> {
  fun doSomething(): K?
  }

This seems like a reasonable type of construct, yet it creates a nullable upper warning. It doesn’t impact the execution of the code, but I’d like to not have this warning without having to do all kinds of comments. How could write the code to eliminate this warning?


#5

yeah, in the case of an output type, I don't think it's redundant, but internally it is


#6

Please note that clients of this class will not be able to distinguish a null returned by doSomething() as an indication that something went wrong from a null that is legitimately a value of T. Java's Map interface is a clasical example of this problem: when get() returns null, we don't know whether it means that the corresponding key is not present, or it is present, but the value for it is null. This warning is reported to let you avoid such problems in your APIs


#7

Yeah, this is making sense now.

The challenge is balancing correctness with simplicity.
Using map as an example, in order to avoid get() being ambiguous, the map implementation would need to take initialization functions for both keys and values. This would add a significant amount of complexity to creating a basic map. You’d also no longer be able to create a map with a nullable upper bound in a generic context.