Nullable types and Non-null types
One of the most common pitfalls in Java programming is accessing a member of a null reference, that results in a NullPointerException, because virtually any reference in a Java program can hold null. It happens so often that we have a casual abbreviation for it: NPE. Also have a look at this talk: "The Billion Dollar Mistake".
Kotlin's type system is aimed to eliminate NullPointerException's from our code. The only possible causes of NPE's may be
- Someone had explicitly thrown is (throw NullPointerException())
- Someone called external Java code that caused it
- There's data inconsistency w.r.t initialization (an uninitialized this available in a constructor is used somewhere)
In Kotlin the type system distinguishes between references that can hold null (nullable references) and those that can not (non-null references). For example, a regular variable of type String can not hold null:
var a : String = "abc" a = null // compilation errorTo allow nulls, one declares a variable as nullable string, written String?:
var b : String? = "abc" b = null // okNow, if you call a method on a, it's guaranteed not to cause an NPE, so you can safely say
val l = a.length()But if you want to call the same method on b, that would not be safe, and the compiler reports an error:
val l = b.length() // error: variable 'b' can be nullBut we still need to call that method, right? There are a few ways of doing that.
Checking for null in conditions
First, you can explicitly check if b is null, and handle the two options separately:
val l = if (b != null) b.length() else -1The compiler tracks the information about the check you performed, and allows the call to length() inside the if. More complex conditions are supported as well:
if (b != null && b.length() > 0) print("String of length ${b.length()}") else print("Empty string")Note that this only works where b is immutable (i.e. a local val or a member val which has a backing field and is not overridable), because otherwise it might happen that b changes to null after the check.
Safe calls
Your second option is the safe call operator, written ?.:
b?.length()This returns b.length() if b is not null, and null otherwise. The type of this expression is Int?.
Safe calls are useful in chains. For example, if Bob, an Employee, may be assigned to a Department (or not), that in turn may have another Employee as a department head, then to obtain the name of Bob's department head, if any), we write the following:
bob?.department?.head?.nameSuch a chain returns null if any of the properties in it is null.
Elvis operator
When we have a nullable reference r, we can say "if r is not null, use it, otherwise use some non-null value x":
val l : Int = if (b != null) b.length() else -1Along with the complete if expression, this can be expressed with the Elvis operator, written ?::
val l = b?.length() ?: -1If the expression to the left of ?: is not null, the elvis operator returns it, otherwise it returns the expression to the right. Note that the right-hand side expression is evaluated only if the left-hand side is null.
The !! operator
The third option is for NPE-lovers. One can write b!!, and this will return a non-null value of b (e.g., a String in our example) or throw an NPE if b is null:
val l = b!!.length()Thus, if you want an NPE, you can have it, but you have to ask for it explicitly, and it does not appear out of the blue.
By the way, !! is added for conciseness, and formerly was emulated by an extension function from the standard library, defined as follows:
inline fun <T : Any> T?.sure() : T = if (this == null) throw NullPointerException() else thisSafe casts
Regular casts may result into a ClassCastException if the object is not of the target type. Another option is to use safe casts that return null is the attempt was not successful:
val aInt : Int? = a as? IntBest practices related to this feature
J. Bloch, Effective Java. Second Edition
Item 38: Check parameters for validity
Item 43: Return empty arrays or collections, not nulls
Null Object Design Pattern
(Originally proposed by B. Woolf )
Similar features in other languages
In Java, one can use annotations on methods and parameters (or on types, when JSR-308 is accepted), these annotations can be used by external tools to verify null-safety. For example, one can use the @NotNull annotation supported by IntelliJ IDEA.
Scala promotes using the Option type to control absent values. This introduces run-time overhead because values are wrapped into objects of type Option, and the syntax is a little verbose.
C# has Nullable types that boil down to wrapping references into value types allocated on the stack, and there's no actual static checks that would prohibit calling methods on a null reference.
Groovy has Safe navigation and Elvis operators.
Gosu's approach is close to ours.

48 Comments
comments.show.hideJul 20, 2011
Anonymous
Any plans on adding Design By Contract type features other than null checking. It is quite cumbersome in most languages to check for preconditions (postconditions, invariants) and then copy the precondition text into the function doc and then finally write a unit test to exercise the precondition check.
For example:
/** does it.
@param i cannot be < 0 or > 100.
@return will never be less than zero
*/
int doIt(Int i)
Instead I'd like to be able to write (maybe this isn't the best syntax but you get the idea). The conditions would be part of the method signature and therefore they don't have to be doc'd or tested (unless you want to make sure they don't change).
/** does it. */
int (< 0) doIt(int (< 0 || > 100) i)
aside from reducing boilerplate docs, tests, etc. It would be cool if the compiler could check these constraints at compile time. I'm thinking something similar to what microsoft is doing with specsharp & code contracts
Jul 21, 2011
Andrey Breslav
We'll probably have it as a compiler plugin
Jul 21, 2011
Anonymous
Typo: "ClassCastException is the object" should be "ClassCastException if the object"
Jul 21, 2011
Maxim Shafirov
Thanks, corrected
Jul 21, 2011
Anonymous
How are static non-null class fields ensured when running code from inside field intializers? Does nonnull provide a hard constraint within the context of the ordering of initializers.
Does this mean that fields that need to be initialized in the constructor can't be nonnull ?
Any chance of a 'assign once' modifier for variables ?
Jul 21, 2011
Maxim Shafirov
We do the same level of assuredness of nonnullability as Java does for final fields being actually final. In some obscured initialization logic where reference to this is escaped before initialization is complete one may see final field being null even though it definitely initialized to some nonnull value.
Jul 22, 2011
Anonymous
Looks very much like Nice which also assumes any Java code may return null unless you tell it otherwise by defining a more refined type signature for the import.
Jul 23, 2011
Anonymous
How do you solve the null-safety with collections?
Question 1:
How do arrays get instantiated and initialized?
A normal array with not nullable items:
vala:Array<String>=Array<String>(5)// must not compile, because the items must not be nullvalb:Array<Int>=Array<Int>(5)// must also not compile, but 'Int' may have the default value '0'valc:Array<Int>=array("a","b","c","d","e")// is OKvald:Array<Int>=array(1,2,3,4,5)// is OKAn array which can contain null-references may look like this:
valx:Array<Int?>=Array<Int?>(10)// is OK, because the items can be nullif(9inx.indices)// check for lengthx[9]=null// is OKOr a nulllable array which can contain null-references:
valy:Array<Int?>?=Array<Int?>(10)if(9iny?.indices)// check for null and length// ^-- Would 'in' in combination with the safe call work?// What's with 'if(y?.length() > 9)' or 'if(y?length() > 9)'?{y[9]=null// is OK// Get the valuevalz:String=y[9]?.toString()?:"<undefined>"}If the items must not be null, how do you initialize an array in a loop?
vala:Array<String>=Array<String>(5)// requires, that this is valid – even if// the items are not nullable// the compiler has to forbid access to the array until it's completely initializedfor(iina.indices)a[i]="Item"+(i+1)// now, we can access the arrayvalitem=a[0]Maybe one can specify a default value for initialization:
vala:Array<String>=Array<String>(5,"<empty>")// initializes all items with "<empty>"valitem=a[0]// is valid, because it's initialized// set custom valuesfor(iina.indices)a[i]="Item"+(i+1)Or a function for initialization:
vala:Array<String>=Array<String>(5,index=>"Item"+(index+1))Or does there exist a special construct for initialization of collections?
Question 2:
What's with a generic dictionary? How does the developer of the dictionary specify, that the key must not be null? Or must null explicitly be allowed?
classDictionary<Key/* must not be null */,Value/* can be null */>...Dictionary<String,String>// is OKDictionary<String,String?>// is OKDictionary<String?,String>// is invalid; must not compileDictionary<String?,String?>// is also invalid; must not compileBest regards,
JMP
Jul 26, 2011
Andrey Breslav
Your question one is a very good point. I would like to mention your name to give you credit for it. Please, feel free to contact me at andrey.breslav[]jetbrains.com.
As of question two: if the generic dictionary class does not admit null keys at all, its declarations is:
classDictionary<K:Any,V>{...}As the upperbound for K is Any, a nullable type cannot go there. The default upperbound (the one for V, for example) is Any?, and admits nullable types.
Jul 24, 2011
Anonymous
Tipo: The link under "What's next" should probably be "Expressions", not "Exceptions".
iu--
Jul 26, 2011
Andrey Breslav
Fixed. Thanks
Aug 04, 2011
Anonymous
Maybe add "?" as a postfix-operator also, so that you can write:
instead of
Aug 04, 2011
Andrey Breslav
This syntax is ambiguous:
value?.foo()
is it
(value?).foo()
or
value ?. foo()
?
Aug 04, 2011
Anonymous
Not if you define ?. and ? as separate tokens. And if you want to call a method on the result of x?, you have to use parens or a space.
This way it would be avoidable to write lots of (x != null) as in Java.
Aug 05, 2011
Andrey Breslav
What about the converse, i.e. (value != null), which occurs more often: how do we write it?
!value?
looks like broken Spanish
Aug 05, 2011
Anonymous
Ups, yes, sorry, my intention was of course to use x? for (x != null) because it's used more often and
looks quite readable.
Aug 05, 2011
Andrey Breslav
!value? will still occur, and it looks strange, but you are right we should look into some ways of shortening null-checks
Aug 05, 2011
Anonymous
I still think, the ? postfix is the most logical choice, because it mirrors the declaration syntax:
Of course negation could use !?, but
would look even stranger. So while
may look a bit strange, it's quite logical.
The prefix versions:
don't look to nice either and lose the connection to the declaration syntax.
Of course you could also add "unless" to the language to be able to write
and at the same time improve readability for expressions like
but I'm not sure if this would be a good idea...
OTOH you have things like "!is", so maybe just allow to write
Aug 05, 2011
Andrey Breslav
Note that it mirrors the declaration syntax in a reversed way (well, like a mirror does):
at a declaration site ? means "may be null"
at use-site, you suggest, it means "not null"
The !if will not work, because if is an expression.
Aug 22, 2011
Anonymous
! and ? look equally "strong" and should maybe be used for similar purposes...
Maybe use a different sign for negation, e.g. ^:
Then you could use ! for the null test:
instead of
and
instead of
Aug 23, 2011
Anonymous
In another thread, I suggested a prefix "@" or some other symbol, since most existing unary operators (!, ~, etc.) are prefix. So you would have:
if (@a) ...
if (!@a) ...
if (@a && !@b && @c && !@d) ...
Prefix "?" might also be a possibility, although I personally find "if (!?a)" difficult to visually parse. I prefer the prefix form to the postfix form, though.
Aug 22, 2011
Anonymous
Aug 22, 2011
Andrey Breslav
1. a?.b() means
if(a!=null)a.b()elsenullAnd a?b() means
if(a!=null&&a.b())aelsenull2. See this branch of comments.
Aug 22, 2011
Anonymous
...ah, OK, 2. has already been discussed, sorry...
Aug 24, 2011
B. K. Oxley (binkley)
re: npe(). Wow, you are really rubbing it in Java's face. A function to recreate the least popular error of all times, so code can break at runtime instead of compile time. I admire your brazenness.
Aug 24, 2011
Andrey Breslav
Well, I wouldn't put it that way
Jan 11, 2012
B. K. Oxley (binkley)
Is System.out nullable? That is just ... sad.
System.out?.println("Hello, world\!")Any likelihood to special case idioms like this from the JDK? Although one could technically set out & err to null, it would be obscure. Were I reviewing "System.setOut(null)" in a fellow's code, I'd call them out on it.
Jan 11, 2012
Andrey Breslav
Well, the standard library will hide this from you. To support other cases we are working on a facility that would know that Java types are not nullable sometimes.
Jan 18, 2012
Alexander Kosenkov
I would add 4th item to the list of possible NPE sources: Multithreading done wrong. At least, this might be a remark to 3rd point.
Possible example:
varlen=0if(this.b!=null)// another thread changes this.b at this moment to null// but compiler still thinks that this.b has valuelen=this.b.length()// oops?Jan 18, 2012
Andrey Breslav
AFAIU, this situation is impossible. Kotlin wouldn't believe the null check if b is mutable. And if it isn't, the only possible change is from null to something else, not the other way around.
I'll add this to the docs above.
Jan 19, 2012
Alexander Kosenkov
Thank you for clarification!
Does it mean that it's not possible to use ` ?. ` operator for accessing class property?
As I understand, correct implementation must involve copying the value from property to synthetic local variable:
vallen=this.someNullableString?.length()// must be implemented equally to:val_tmp=this.someNullableString// someNullableString can be safely set to null from another thread nowvallen=if(_tmp!=null)_tmp.length()elsenull;// same as _tmp?.length()Is it implemented this way?
Jan 19, 2012
Andrey Breslav
You can use ?. for a member property, because both the null-check and the call work on the same value (there's only one read-access to the property).
In the byte code there's no need in a local variable, a simple DUP instruction is sufficient.
Nov 24, 2012
Peter Meix
I am observing the following behavior (kotlin-plugin, WebDemo)
Could you please clarify the reason for this behavior?
Why does the null check behave differently depending on val/var?
Thanks!
Nov 26, 2012
Andrey Breslav
A val is guaranteed to never change, thus it is safe to rely on a check performed somewhere. A var may have changed since the check was performed.
We will probably improve the analyzer and support local vars that don't change in fact. But now that case is not supported.
Nov 26, 2012
Peter Meix
ok, so this primarily addresses concurrency issues, does it?
It is a pity since there are many use cases where we know we are in a single threaded environment and there is no chance a var may become null. I am looking forward to the analyzer improvement, but I cannot imagine how this could be done.
Feb 21, 2012
Boris Okunskiy
Are nullable types somehow retained in bytecode? Is there a way to introspect the nullability of a property using reflection? Maybe the compiler could implicitly add some specific annotation to such properties? This could be useful in ORMs which could emit NOT_NULL statements in DDL automatically.
Feb 21, 2012
Andrey Breslav
This is exactly what Kotlin does: we add annotations with complete type information
May 16, 2012
Boris Okunskiy
I have yet another question about null-safe design approach. Sorry if you've already covered it elsewhere.
In Scala, Options (thus nullable types) are treated pretty much like collections: for non-null value we have a one-element collection; or we get Nil otherwise. This approach brings a couple of techniques I currently can't imagine my life without:
Now I can't imagine all such small code fragments implemented with IF-statements and elvis operators. So, how such things will be going in Kotlin?
May 16, 2012
Andrey Breslav
All these operations can be defined as (extension) functions in Kotlin, and they are there in the library: https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/kotlin/nullable/Nullables.kt
May 16, 2012
Boris Okunskiy
Great news for me :) Thanks!
Jul 02, 2012
Danila Ponomarenko
I found myself in situation like this:
Here T possibly can be nullable and T? is always nullable. How can I make NPE to be thrown only if T is not nullable and event value is null?
I mean somethig like this:
upd: I've found solution for this particular case
but there is still no way to call method with generic parameter with surely nullable argument and have npe only if argument is null and generic parameter is not nullable
Oct 07, 2012
Ian Clarke
How do you recommend dealing with external libraries, where Kotlin typically assumes that they are returning a value that might be null, whereas in reality they will never return null?
For example, in the Google Guava libraries, BloomFilter.create(..) always returns a BloomFilter, but Kotlin assumes that it could be null, even though this will never happen.
Should I just use the !! operator on the value returned by the function, or is there a better way to deal with this?
Oct 07, 2012
Andrey Breslav
See it here: http://blog.jetbrains.com/kotlin/using-external-annotations/
Meanwhile, we are working on a tool that would infer those annotations automatically. It will be available soon.
Feb 09, 2013
Jonathan
I'm new to Kotlin, but I really like its null-safety features with the various uses of '?'. It's all very consistent and elegant.
But here's a suggestion: the only place where you don't use the ? symbol is in the keyword null itself. This is inconsistent (and seems old-fashioned, like the ugly days of C++) - and of course null hardly ever needs to be mentioned in code anyway.
So: why not simply use the symbol ? itself:
You could always deprecate null for the moment & remove it later.
If this is possible, I would love Kotlin.
Feb 09, 2013
Jonathan
(deleted)
Feb 12, 2013
Andrey Breslav
Thanks for your suggestion, but im my opinion, this would make the syntax cumbersome and unfamiliar where it need not be. Also, while unambigous for the compiler, it will be rather ambiguous for the eye.
Apr 14, 2013
Mohammad Shamsi
Hi,
Any reason why two '!' in :
why not a single '!':
is it just a preference or there is a explanation behind it ?
Apr 14, 2013
Andrey Breslav
It's more visible and causes no confusion with negation.