#android #kotlin #nullable
#Android #котлин #обнуляемый
Вопрос:
Я должен следовать объявлению переменной:
var baseItemList: MutableList<BaseDataItem>? = null
при написании строки:
baseDataItemsList?.get(position).getObjectTypeNum()
Я получаю сообщение об ошибке, в котором говорится, что:
Только безопасные (?.) или ненулевые утвержденные (!!.) Вызовы разрешены для обнуляемого получателя типа BaseDataItem?
но метод get не возвращает BaseDataItem? , только BaseDataItem, поскольку BaseDataItem внутри скобок не имеет вопросительного знака. Может ли кто-нибудь объяснить мне эту ошибку и почему я должен добавить этот вопросительный знак?
Комментарии:
1.Ваши два фрагмента кода не совпадают. Один ссылается на
baseItemList
, а другой ссылается наbaseDataItemsList
. Но, предполагая, что это действительно одно и то же,baseDataItemsList?.get()
может бытьnull
, потому что, хотя список содержит только не-null
значения,baseDataItemsList
сам по себе может бытьnull
.2. @CommonsWare может быть, я чего-то не понимаю, но как может
baseDataItemsList?.get()
быть null, если он проходит?.
проверку? Не могли бы вы, пожалуйста, объяснить3. @Rey, ты ответил на мой вопрос 🙂
4.
?.
это не «проверка». Он возвращаетсяnull
, если приемник (левая сторона) естьnull
. Итак, еслиbaseDataItemsList
естьnull
,baseDataItemsList?.anyFunctionYouWantToCall()
будет вычислятьсяnull
.5.
baseDataItemsList?.get(...)
возвращает null, еслиbaseDataItemsList
равно null
Ответ №1:
Глядя на этот код:
baseDataItemsList?.get(position)?.getObjectTypeNum()
Вызов ?.get(position)
возвращает позицию, если baseDataItemsList
она не равна нулю, но в противном случае возвращает значение null . Таким образом, даже несмотря baseDataItemsList.get()
на то, что возвращает BaseDataItem
значение, не равное нулю (возможно вызвать только в том случае, если baseDataItemsList
оно не равно нулю), безопасный с нулевым baseDataItemsList?.get()
значением вызов возвращает BaseDataItem?
значение, равное нулю , где условие null указывает, что baseDataItemsList
оно равно null . Поэтому вы должны использовать ?.getObjectTypeNum()
для учета этого.
Примечание: на мой взгляд, объединение var
с изменяемой коллекцией часто является запахом кода, потому что вы делаете что-то изменяемым двумя разными способами, что делает его более подверженным ошибкам в работе.
Комментарии:
1. извините, но я все еще не могу понять. Если проверить, есть ли baseDataItemsList? «передано», почему результат метода get должен быть также с? . если есть какой-либо опасный объект null? Разве цепочка (во время выполнения) не останавливается, когда первая часть безопасных вызовов возвращает значение null? Я думал, что метод get даже не будет запущен. Я сделал ссылку var и из MutableType, так как в большинстве случаев я буду добавлять / удалять из списка, но есть ситуация, когда я не хочу восстанавливать весь список другим списком, на который у меня есть ссылка
2. Это не проверка на прохождение / сбой.
?.
означает, что если не null, верните результат вызова this , иначе верните null .3. @Tenfour04, не могли бы вы сказать мне, работает ли as по-другому и не участвует ли в цепочке безопасных вызовов? в следующем коде: (держатель как ViewHolder)?. leagueNameTextView.text , если holder не является ViewHolder , это означает, что значение null возвращается для всех выражений слева от свойства text , тогда попытка запустить null.text кажется проблемой, но компилятор не заставляет меня ставить знак вопроса перед свойством text . Не могли бы вы объяснить мне, почему?
4.
holder as ViewHolder
приводит его к ненулевому ViewHolder . Это явное, небезопасное приведение, и если holder имеет значение null или не является ViewHolder , вы получите исключение NullPointerException или ClassCastException соответственно во время выполнения. Если вы хотите выполнить безопасное приведение к обнуляемому ViewHolder, вы бы использовалиholder as? ViewHolder
.5. @Tenfour04 еще раз спасибо 🙂 Я не заметил, что если забыл вопросительный знак при использовании as?.. Спасибо!!! но проблема с as? что я должен делать это каждый раз, когда использую holder ? Приведение не сохраняется? Или, может быть, вставить as? в if statmement : if(держатель как? ViewHolder != null)
Ответ №2:
Используйте функции области видимости Котлина, например let
, область видимости, чтобы избежать этого предупреждения:
baseDataItemsList?.let { baseDataItemList ->
baseDataItemList.get(position).getObjectTypeNum()
}
Таким образом, вы утверждаете, что baseDataItemList не может находиться null
внутри области let
видимости. Если вы хотите узнать больше об этой теме, загляните в документацию
Комментарии:
1. Является ли это более «правильным» способом сделать это, а не так, как я это написал (с другим безопасным вызовом)?