Skip to content

Instantly share code, notes, and snippets.

@robfletcher
Last active February 24, 2016 18:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robfletcher/fe1591ddbc8144289fdf to your computer and use it in GitHub Desktop.
Save robfletcher/fe1591ddbc8144289fdf to your computer and use it in GitHub Desktop.
Example of how Kotlin treats nullability of Java types
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)
}
}
}
}
}
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