Init a variable of type Sensor by lazy


#1

When initializing a val of type Sensor by lazy the compiler ignores that the value returned can be null

Note: The val is declared as Sensor and not Sensor?

Code

private val sensorManager by lazy { getSystemService(Context.SENSOR_SERVICE) as SensorManager }

private val proximitySensor: Sensor by lazy { sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) }

Kindly note that sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY) can also return null

Shouldn’t it raise a compile time error when assigning a nullable to a val which is non-null?

When accessed from code, if proximitySensor is null and tried to access it. It gives a runtime exception as expected.
'java.lang.String android.hardware.Sensor.getName()' on a null object reference

Also, the Android Studio gives a warning when checking for null as we have not declared it as Sensor?

if (proximitySensor == null) {
            label_proximity.text = getString(R.string.error_no_sensor)
        }

Using Sensor? solves the problem but I the code should not compile without declaring a nullable type with ?


#2

You will find that getDefaultSensor(...) returns a platform type. The Kotlin compiler cannot know whether the returned value can be null, because you cannot specify nullability in Java, and the compiler cannot analyze the full code behind the method being called.

It is your responsibility to handle platform types correctly:

  • It is definitely not null: Assign it to a non-nullable variable.
  • It may be null: Handle the null case by failing or providing a fallback.

The documentation of the Java method should tell you about the nullability of the returned value.


#3

But shouldn’t the exception be thrown when a null value is being assigned?


#4

Yes it should: “If we choose a non-null type, the compiler will emit an assertion upon assignment.” See the last paragraph of https://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types

So this sounds like a bug.


#5

… because of a null-pointer exception or an assertion that Kotlin generates to prevent nulls from propagating. From the docs, I’m not sure what this line exactly means. Maybe it is supposed to happen this way.


#6

There’s some discussion on the stackoverflow question: https://stackoverflow.com/questions/50173899/null-property-when-accessing-lazy-non-nullable-property-of-android-sensor/50176388#50176388


#7

Yup. It’s a good discussion, I asked that question.