Должен ли я удалить обнуляемость переопределенных методов, которые не помечены как обнуляемые в унаследованном классе - PullRequest
5 голосов
/ 15 октября 2019
Android 3.5.1

Я использовал WebView и заметил, что при переопределении некоторых методов все параметры имеют типы Nullable:

webview.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
         return super.shouldOverrideUrlLoading(view, request)
    }
}

Что означает, что я должен использовать оператор safe call дляиспользуй их. Однако, когда я посмотрел на класс WebViewClient, в котором я переопределил метод, они не указаны как аннотация nullable в коде Java.

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    return shouldOverrideUrlLoading(view, request.getUrl().toString());
}

Так что мне остается подумать, удалить ли яОбнуляемость из переопределенного метода или оставить их?

Ответы [ 6 ]

8 голосов
/ 18 октября 2019

Источником этой проблемы является Совместимость между Java и Kotlin . Между Java и Kotlin существуют некоторые базовые языковые различия, что вызывает проблемы взаимодействия. Android Studio предоставляет некоторые Lint проверки для их предупреждения, такие как Unknown Nullness. ( ссылка )

enter image description here

Взглянув на подробности Unknown nullness Проверка Lint с android.com , мы увидим, что:

Чтобы улучшить ссылочный код с Kotlin, рассмотрите возможность добавления здесь явной информации об аннулировании с помощью @NonNull или @Nullable.

и developer.android.com :

Если вы используете Kotlin для ссылки на аннотированный элемент имени, определенный в классе Java ( например a String), компилятор не знает, отображается ли String на String или String? в Kotlin. Эта неоднозначность представлена ​​через тип платформы , String!.

и на kotlinlang.org :

Любая ссылка в Java может быть null , что делает требования Kotlin строгой нулевой безопасностинецелесообразно для объектов, поступающих с Java. Типы Java объявлений обрабатываются специально в Kotlin и называются типами платформ .

Поэтому, когда мы переопределяем метод Java, чтобы его аргументы не были аннотированы аннотациями недействительности, IDE добавляет обнуляемый знак (?) для аргументов в классе Kotlin. Это приводит к избеганию выброса NullPointerException при вызове метода в Java путем передачи значения null для одного из аргументов.

webview.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(
        view: WebView, // <- potential to throw NPE before executing the function block!
        request: WebResourceRequest // <- as well!
    ): Boolean {
        return super.shouldOverrideUrlLoading(view, request)
    }
}

В двух словах, мы НЕ ДОЛЖНЫ удалить ? знак из аргументов функции, когда переопределенный метод определен в Java классе.

2 голосов
/ 20 октября 2019

Если виртуальный метод в Java не определяет каким-либо образом обнуляемость своих параметров, например, с помощью аннотаций @Nullable / @NotNull, вы можете выбрать обнуляемость в любом случае при переопределении этого метода в Kotlin.

Но как выбрать?

  • Сначала вы можете обратиться к документации по методу и проверить контракт по методу. Указывает ли это, что метод может быть вызван с нулями, и что эти значения будут означать при передаче в метод?

    В этом конкретном случае WebViewClient.shouldOverrideUrlLoading Страница документа метода ничего не говорит о пустых значениях, поэтому ее можно считать доказательством того, что ее параметры должны быть non-nullable .

  • Во-вторых, если вы все еще не уверены в обнуляемости после просмотра документов, вы можете подумать, что бы вы сделали со значением параметра NULL, если вы его получите. Если единственное разумное в этой ситуации - выдать исключение, вы можете делегировать эту проверку коду проверки параметров, сгенерированному Kotlin, объявив параметры как необнуляемые.
2 голосов
/ 15 октября 2019

В отличие от Kotlin, объекты Java по умолчанию могут принимать значения NULL

@ Nullable аннотация используется только для таких операций, как анализаторы кода (например, если параметр @Nullable не обрабатывается внутриметод затем будет отображать предупреждение)

@ NonNull аннотация используется, чтобы указать, что полученное значение не может / не будет нулевым

if(@NonNull){
      can omit ? check
}else if(@Nullable){
     Mandatory to put ? check
}else(No annotation){
     Not mandatory but put on safer side .
     Passing null from Java into Kotlin fun without ? will lead to NPE
    if(putting ? check){
     java equivalent Kotlin param  (@Nullable Webview view)
    } else{
     java equivalent Kotlin param (@NonNull Webview view)
    }

}

ТакжеСм. Это: https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#null-safety

1 голос
/ 20 октября 2019

На уровне языка это можно обобщить:

Для правильной совместимости Java код Kotlin должен отражать аннотации кода Java.

Линтер только жалуется на отсутствие аннотаций в другом направлении, для взаимодействия Kotlin.

См. эту недавнюю статью на Как написать дружественный к Java код Kotlin?

1 голос
/ 19 октября 2019

Нулевая ссылка является довольно очевидным исключением для всех, потому что все началось с нативной разработки на C / C ++. Ссылка на объекты в памяти может отсутствовать или очищаться по разным причинам. Java была разработана с учетом тех родных языков , которые везде принимают нулевые указатели.

Управление всеми изменяемыми состояниями доставляет удовольствие с тысячами микросервисов. Это вызывает много обходных путей для ссылки Nullable. - Optional Объекты - Макет Null Object - Wrappers вокруг ссылок - Annotations и т. Д. И все это для предотвращения изменения состояния где-то выделенногообъект.

Наконец, Котлин здесь не первый. Scala с неизменными состояниями имела отличный опыт использования и поддержки приложений. Итак, отвечая на этот вопрос и резюмируя, Java была разработана таким образом из своего родительского C ++, и вы должны ожидать нулевые значения везде. По этой причине мы все еще проверяем ссылку на ноль, даже если она не аннотирована @Nullable. И точно так же Kotlin управляет использованием Java, и поэтому вам нужно обрабатывать нулевые значения в переопределенных методах.

1 голос
/ 17 октября 2019

Они не указаны как аннулируемые аннотации в коде Java.

Если это правда, обратите внимание, что вы рискуете выбросить NullPointerException, если не указано как аннулируемые аннотации в коде Java иназначить нулевое значение. поэтому удалите обнуляемость из переопределенного метода, если она не указана как аннулируемая аннотация в коде Java.

Подробнее читайте это также это

...