Last active
February 24, 2016 18:26
-
-
Save robfletcher/fe1591ddbc8144289fdf to your computer and use it in GitHub Desktop.
Example of how Kotlin treats nullability of Java types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.jetbrains.spek.api.* | |
class InteropNullabilitySpec : Spek() { | |
init { | |
given("a java object with null state") { | |
val obj = JavaStringWrapper(null) | |
on("calling a getter that will return null") { | |
it("allows me to assign the result to a nullable type") { | |
val s: String? = obj.value | |
shouldBeNull(s) | |
} | |
it("fails at runtime if I assign the result to a non-nullable type") { | |
shouldThrow(IllegalStateException::class.java) { | |
val s: String = obj.value | |
} | |
} | |
it("allows me to directly access the value") { | |
shouldBeNull(obj.value) | |
} | |
} | |
on("calling a getter annotated with @NotNull") { | |
it("fails at runtime if I assign the result to a nullable type") { | |
shouldThrow(IllegalStateException::class.java) { | |
val s: String? = obj.valueNotNull | |
} | |
} | |
it("fails at runtime if I assign the result to a non-nullable type") { | |
shouldThrow(IllegalStateException::class.java) { | |
val s: String = obj.valueNotNull | |
} | |
} | |
it("fails at runtime if I access the value at all") { | |
shouldThrow(IllegalStateException::class.java) { | |
obj.valueNotNull | |
} | |
} | |
} | |
on("calling a getter annotated with @Nonnull") { | |
it("allows me to assign the result to a nullable type") { | |
val s: String? = obj.valueNonnull | |
shouldBeNull(s) | |
} | |
it("fails at runtime if I assign the result to a non-nullable type") { | |
shouldThrow(IllegalStateException::class.java) { | |
val s: String = obj.valueNonnull | |
} | |
} | |
it("allows me to directly access the value") { | |
shouldBeNull(obj.valueNonnull) | |
} | |
} | |
on("calling a getter that will return a list with null elements") { | |
it("allows me to assign the result to a list with nullable elements") { | |
val l: List<String?> = obj.values | |
shouldNotBeNull(l) | |
shouldBeNull(l.first()) | |
} | |
it("allows me to assign the result to a list with non-nullable elements but fails at runtime when I try to use an element") { | |
val l: List<String> = obj.values | |
shouldNotBeNull(l) | |
val s: String = l.first() // interesting no null check is done here | |
shouldThrow(NullPointerException::class.java) { | |
s.length | |
} | |
} | |
} | |
on("calling a method with a parameter") { | |
it("allows me to pass a nullable type with a null value") { | |
val s: String? = null | |
obj.value = s | |
shouldBeNull(obj.value) | |
} | |
it("allows me to pass a nullable type with a non-null value") { | |
val s: String? = "foo" | |
obj.value = s | |
shouldEqual(s, obj.value) | |
} | |
it("allows me to pass a non-nullable type") { | |
val s: String = "foo" | |
obj.value = s | |
shouldEqual(s, obj.value) | |
} | |
} | |
on("calling a method with a parameter annotated with @NotNull") { | |
it("will not compile if I try to pass it a nullable type") { | |
val s: String? = "foo" | |
obj.valueNotNull = s!! | |
shouldEqual(s, obj.value) | |
} | |
it("allows me to pass a non-nullable type") { | |
val s: String = "foo" | |
obj.valueNotNull = s | |
shouldEqual(s, obj.value) | |
} | |
} | |
on("calling a method with a parameter annotated with @Nonnull") { | |
it("will not compile if I try to pass it a nullable type") { | |
val s: String? = "foo" | |
obj.valueNonnull = s!! | |
shouldEqual(s, obj.value) | |
} | |
it("allows me to pass a non-nullable type") { | |
val s: String = "foo" | |
obj.valueNonnull = s | |
shouldEqual(s, obj.value) | |
} | |
} | |
} | |
given("a java object with non-null state") { | |
val obj = JavaStringWrapper("foo") | |
on("calling a getter that will return null") { | |
it("allows me to assign the result to a nullable type") { | |
val s: String? = obj.value | |
shouldEqual("foo", s) | |
} | |
it("allows me to assign the result to a non-nullable type") { | |
val s: String = obj.value | |
shouldEqual("foo", s) | |
} | |
} | |
on("calling a getter annotated with @NotNull") { | |
it("allows me to assign the result to a nullable type") { | |
val s: String? = obj.valueNotNull | |
shouldEqual("foo", s) | |
} | |
it("allows me to assign the result to a non-nullable type") { | |
val s: String = obj.valueNotNull | |
shouldEqual("foo", s) | |
} | |
} | |
on("calling a getter that will return a list with non-null elements") { | |
it("allows me to assign the result to a list with nullable elements") { | |
val l: List<String?> = obj.values | |
shouldNotBeNull(l) | |
shouldNotBeNull(l.first()) | |
} | |
it("allows me to assign the result to a list with non-nullable elements") { | |
val l: List<String> = obj.values | |
shouldNotBeNull(l) | |
val s: String = l.first() | |
shouldBeTrue(s.length > 0) | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Collections; | |
import java.util.List; | |
import javax.annotation.Nonnull; | |
import org.jetbrains.annotations.NotNull; | |
public class JavaStringWrapper { | |
private String value; | |
public JavaStringWrapper(String value) { | |
this.value = value; | |
} | |
public String getValue() { return value; } | |
@NotNull public String getValueNotNull() { return value; } | |
@Nonnull public String getValueNonnull() { return value; } | |
public List<String> getValues() { return Collections.singletonList(value);} | |
public void setValue(String value) { this.value = value; } | |
public void setValueNotNull(@NotNull String value) { this.value = value; } | |
public void setValueNonnull(@Nonnull String value) { this.value = value; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment