Seguridad nula en las bibliotecas henetworkingadas de Java utilizadas en los proyectos de Kotlin

Digamos que tengo un código particular en la biblioteca de Java antigua / henetworkingada:

public class JavaClass { private String notNullString; private String nullableString; private String unannotatedString; public JavaClass(@NotNull String notNullString, @Nullable String nullableString, String unannotatedString) { this.notNullString = notNullString; this.nullableString = nullableString; this.unannotatedString = unannotatedString; } @NotNull public String getNotNullString() { return notNullString; } @Nullable public String getNullableString() { return nullableString; } public String getUnannotatedString() { return unannotatedString; } } 

Los primeros dos parameters están anotados correctamente con annotations @NotNull y @Nullable (utilizando jetbrains.annotations). El tercero ( cadena no anotada ) se deja sin la anotación adecuada.

Cuando uso esta class en mi código de Kotlin y establezco todos los arguments de constructor en valores no nulos, todo está bien:

 val foo = JavaClass("first string", "second string", "third string") println("Value1: ${foo.notNullString.length}") println("Value2: ${foo.nullableString?.length}") println("Value3: ${foo.unannotatedString.length}") 

El primer valor no es nulo, así que puedo acceder a él sin una llamada segura. Segundo valor y necesito usar la llamada segura (nullableString? .length), si no, tengo un error en time de compilation, hasta ahora todo bien. En el tercer valor (unannotatedString) puedo usarlo sin una llamada segura, comstack bien.

Pero cuando establezco el tercer parámetro en "nulo" no obtengo un error en time de compilation (no se requiere una llamada segura, solo el time de ejecución NullPointerException:

 val bar = JavaClass("first string", "second string", null) println("Value4: ${bar.unannotatedString.length}") // throws NPE 

¿Es ese comportamiento esperado? ¿El comstackdor de Kotlin no trata los methods Java anotados como los anotados con @NotNull?

El tipo de esa variable desde la vista de Kotlin será String! , que es un tipo de plataforma .

Inicialmente hicieron que todas las variables provenientes de Java pudieran contener nulos, pero cambiaron esa decisión más adelante durante el layout del lenguaje, porque requería demasiada manipulación null y requería demasiadas llamadas seguras que saturaban el código.

En cambio, depende de usted evaluar si un object procedente de Java podría ser null , y marcar su tipo en consecuencia. El comstackdor no aplica security nula para estos objects.


Como ejemplo adicional, si está anulando un método de Java, los parameters serán types de plataforma una vez más, y depende de usted si los marca como nulos o no. Si tienes esta interfaz Java:

 interface Foo { void bar(Bar bar); } 

Entonces estas son implementaciones válidas de Kotlin:

 class A : Foo { fun bar(bar: Bar?) { ... } } class B : Foo { fun bar(bar: Bar) { ... } } 

Cuando el comstackdor de Kotlin no sabe cuál es la capacidad de nulidad de un tipo, ¡el tipo se convierte en un tipo de plataforma , denotado con un único ! :

 public String foo1() { ... } @NotNull public String foo2() { ... } @Nullable public String foo3() { ... } val a = foo1() // Type of a is "String!" val b = foo2() // Type of b is "String" val c = foo3() // Type of c is "String?" 

Esto significa tanto como "No sé de qué tipo es, es posible que deba verificarlo".

El comstackdor de Kotlin no impone la verificación nula en estos types, porque puede ser innecesario:

Cualquier reference en Java puede ser nula, lo que hace que los requisitos de Kotlin de security nula estricta no sean prácticos para los objects provenientes de Java. (…) Cuando llamamos a methods sobre variables de types de plataforma, Kotlin no emite errores de anulabilidad en time de compilation, pero la llamada puede fallar en time de ejecución, debido a una exception de puntero nulo o una afirmación que Kotlin genera para evitar nulos de propagador:

 val item = list[0] // platform type infernetworking (ordinary Java object) item.substring(1) // allowed, may throw an exception if item == null 
  • No se puede save el model de datos que contiene List <Model> con Room ORM Kotlin
  • Encienda un byte
  • Error de Kotlin Fuel REST Client Proxy
  • Cómo llamar a la function baseactivity desde viewmodel en android
  • Casilla de verificación "Incluir soporte de Kotlin" no en Android Studio 3.0 Canary 5
  • Rx Java Retrofit con flatMap se ejecuta solo una vez
  • ¿Cómo serializar / deserializar una matriz de objects personalizados en Kotlin?
  • ¿Hay alguna function de réplica en Kotlin?
  • Cómo convertir String a Long en Kotlin?
  • No se puede encontrar el cuerpo de destino después de ejecutar una aplicación web de Jfinal con kotlin
  • ¿Por qué Kotlin usa la palabra "val" para representar constante?