Kotlin Предупреждение: ненужный безопасный вызов на ненулевом приемнике типа Marker - PullRequest
1 голос
/ 15 января 2020

Как и все, я учусь Kotlin. И я пытаюсь сделать это правильно. Поэтому я объявляю переменную в своем классе:

private lateinit var mLastMarker: Marker

mLastMarker отслеживает последний раз, когда я использовал маркер, поэтому я могу удалить его при создании нового (google maps api). Поэтому при добавлении нового маркера я сначала хочу удалить старый:

// remove last marker (if it exists)
mLastMarker?.remove()

// add this marker to the map
mLastMarker = mMap.addMarker(markerOptions)

, что для меня имеет смысл. Я думаю, что я буду выполнять функцию remove(), только если mLastMarker не равно нулю. Он будет установлен сразу после и, таким образом, будет вызывать remove() каждый раз после первого (когда есть что удалить).

Но я получаю предупреждение. ?. подсвечивается предупреждающим сообщением в заголовке. Что дает? Чего мне не хватает в нулевой безопасности kotlin здесь?

Ответы [ 2 ]

4 голосов
/ 15 января 2020

При lateinit значение null никогда не будет сохранено в вашей собственности. Обратите внимание, что его тип, Marker, не является типом Marker?, допускающим обнуляемость - фактически вы не можете создать свойство, которое может быть как обнуляемым, так и lateinit.

. Используя lateinit, вы говорят, что компилятор не должен проверять обнуляемость в любой момент, и что вы всегда ожидаете, что значение уже будет в свойстве, прежде чем вы его прочитаете Если вы прочитаете его перед установкой, вы не получите null, вместо этого он выдаст исключение. Вы также никогда не сможете вернуть его в неинициализированное состояние, если вы дали ему значение, потому что оно не примет null в качестве нового значения.

В общем, lateinit хорошо, если Вы хотите инициализировать что-то один раз, прежде чем начать его использовать, но по какой-то причине не можете инициализировать его при создании свойства (например, во время создания класса).

Если вам иногда приходится проверять, есть ли у вас текущее значение, лучше использовать свойство, допускающее обнуляемость (хотя вы можете технически проверить, инициализирована ли переменная lateinit, но это не красиво).

1 голос
/ 15 января 2020
private lateinit var mLastMarker: Marker 

Объявляет экземпляр типа Marker.

private lateinit var mLastMarker: Marker?

Объявляет экземпляр типа nullable Marker.

Следовательно, в вашем случае проверка нулевой безопасности ? является избыточной, поскольку mLastMarker не может быть нулевым.

Итак:

mLastMarker?.remove()

Может быть:

mLastMarker.remove()

Смущение, вероятно, вызвано тем, что вы используете lateinit, поэтому я предполагаю, что вы поняли, что значение может быть null. Это немного странно, потому что для компилятора значение не может быть null, но, если вы не назначите значение lateinit где-то перед тем, как получите к нему доступ, на самом деле оно будет "по существу" null (не совсем, но концептуально), и доступ к нему может привести к UninitializedPropertyAccessException

Иногда вам действительно нужно свойство lateinit, но чаще всего вы можете его избежать. Я бы посоветовал взглянуть на ваш код и посмотреть, действительно ли вам нужно, чтобы он был lateinit, или вы можете создать его экземпляр заранее, или, альтернативно, именно там, где он требуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...