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 
  • JsonProperty no funciona mientras la minificación está habilitada
  • Carga GIF usando la versión 4.2.0 de deslizamiento en Kotlin
  • Reino que devuelve datos obsoletos
  • ¿Cómo agrego create-react-kotlin-app como module al proyecto kotlin-multiplataforma?
  • Kotlin constructor secundario
  • ¿Cómo hacer trabajo @Autowinetworking en una class regular?
  • Clases internas de Kotlin en Java visibles públicamente
  • ¿Es posible usar String como PrimaryKey en Android Room?
  • ¿Cómo puedo get una request web actual usando Vert.x Web?
  • La initialization lenta de la propiedad de la class Kotlin no comstackrá
  • Asynctask múltiples requestes de URL consecutivas en Android