8 Stephan Herrmann GK Software A Deep Dive into

8
A
A Deep
Deep Dive
Dive into
into the
the Void
Void
Advanced
null
Type
Annotations
Java 8 ready
Stephan Herrmann
GK Software
8
8
An Old Problem
1965
–
Tony Hoare introduced Null references in ALGOL W
–
“simply because it was so easy to implement”
Photograph by Rama, Wikimedia Commons, Cc-by-sa-2.0-fr
●
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
#2
Still Leading the Charts
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
8
#3
An Expensive Problem
“The Billion Dollar Mistake”
Photograph by Rama, Wikimedia Commons, Cc-by-sa-2.0-fr
●
8
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
#4
8
Many Steps to a Solution
●
–
●
boooom
method contracts
–
●
booooooom
local flow analysis
–
●
booooooooom
recognize patterns
–
●
Since
Since ALGOL
ALGOL W
W
do nothing:
1965
Since
Since Eclipse
Eclipse 3.1
3.1
Since
Since Eclipse
Eclipse Juno
Juno // Java
Java 55
boom
type checking
2005
Since
Since Eclipse
Eclipse Luna
Luna // Java
Java 88
2012
2014
–
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
#5
Alternative Strategy
●
8
Optional
–
a polite way of saying: this value could be missing
–
supports null-less programming
–
doesn't help against existing nulls
–
viable option for from-scratch clean-room new software
–
requires all software to be re-written
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
#7
Obviously Correct
●
Typechecking for null analysis
●
Two kinds of types
–
–
●
This is OK:
●
These are type errors:
8
those that include null
those that don't
Dog? barkAndReturn(Dog dog) {
dog.bark();
return null;
}
Dog barkAndReturn(Dog? dog) {
dog.bark();
return null;
}
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
#8
Typesystem Construction Kit
Strategy
●
Richer types
–
●
–
●
JSR 308
●
add more information
Richer type checking
Type annotations
– org.eclipse.jdt.annotation_2.0
@NonNull @Nullable
●
new typing rules
Stronger guarantees
8
ECJ checks nullness
–
●
compatibility & flow
Stronger guarantees
–
proven absence of errors
–
no NPE
–
no methodNotUnderstood
–
no SWTExecption(thread)
–
no ClassCastException
–
…
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
#9
Ternary or Boolean?
●
Buy @NonNull & @Nullable, get 3 kinds of types
–
●
–
like using raw types in Java 5+
Null
Nulltype
typesafety
safety(type
(typeannotations):
annotations):The
Theexpression
expressionof
oftype
type'List<String>'
'List<String>'
needs
needsunchecked
uncheckedconversion
conversionto
toconform
conformto
to'@NonNull
'@NonNullList<@NonNull
List<@NonNullString>'
String>'
Nirwana: ubiquitous @NonNullByDefault
–
–
–
●
green, red, legacy
Interfacing with legacy code
–
●
8
per class / interface
per package (use package-info.java)
let the compiler complain about missing @NNBD
And back to 2014 reality
–
@NonNullByDefault({})
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 10
Where is: Everywhere?
8
TYPE_USE declarations
DefaultLocation for @NonNullByDefault
PARAMETER
RETURN_TYPE
FIELD
TYPE_PARAMETER
TYPE_BOUND
TYPE_ARGUMENT
ARRAY_CONTENTS
@NonNullByDefault({ … })
class Foo <T extends Bar> {
Foo<String> stringFoo;
Bar[][] bars;
Bar getBar(String name) {
return bar;
}
}
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 11
Where is: Everywhere?
8
DefaultLocation for @NonNullByDefault
●
Not supported
–
non-null by construction
●
●
●
●
–
would need runtime evaluation
●
–
instanceof & cast
no usefull interpretation
●
●
–
new
void
void make(@A
make(@A Foo
Foo this)
this) {}
{}
throws, catch argument
this
@A
receiver in method reference
@A Object::toString
Object::toString
@A
@A Integer.MAX_VALUE
Integer.MAX_VALUE
prefix of static member
constructor
future
●
type declaration
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 12
Where is: Everywhere?
8
...
...
Wildcards
Wildcards and
and the
the use
use of
of type
type variables
variables
are
are always
always excluded
excluded from
from NonNullByDefault.
NonNullByDefault.
DefaultLocation for @NonNullByDefault
●
Not supported
●
No default
–
local variables
●
–
better covered by flow analysis
on type variables & wildcards
●
these obtain nullness via other channels
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 13
Where is: Everywhere?
8
TYPE_USE declarations
DefaultLocation for @NonNullByDefault
PARAMETER
RETURN_TYPE
FIELD
TYPE_PARAMETER
TYPE_BOUND
TYPE_ARGUMENT
ARRAY_CONTENTS
@NonNullByDefault({ … })
class Foo <T extends Bar> {
Foo<String> stringFoo;
Bar[][] bars;
Bar getBar(String name) {
return bar;
}
}
Default default
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 14
Where is: Everywhere?
8
TYPE_USE declarations
DefaultLocation for @NonNullByDefault
PARAMETER
RETURN_TYPE
FIELD
TYPE_PARAMETER
TYPE_BOUND
TYPE_ARGUMENT
ARRAY_CONTENTS
@NonNullByDefault({ … })
class Foo <T extends Bar> {
Foo<String> stringFoo;
Bar[][] bars;
Bar getBar(String name) {
return bar;
}
}
Default default
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 15
Great Expectations
●
ECJ will not “make” your program “null safe”
●
It will hurt
–
–
–
●
pin-point
●
design decisions you failed to make
●
contradictory assumptions
a false positive?
type checker will need your help
rules & obligations
Application development
–
●
8
free to move obligations around
Tension in API design
–
–
strict for effective null checking
flexible for wide range of re-use
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 16
Generic API
●
The classic declaration
–
●
Unconstrained type parameter:
●
public interface List<T> { … }
Client side
–
Free to choose the type argument:
●
●
●
8
List<@NonNull Person>
List<@Nullable Person>
Implementer
–
No knowledge about “free” type variable T
–
Must assume the worst
●
●
need to check on dereference
cannot assign null to a T variable
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 17
8
Constraining Type Parameters
●
●
Admit only @NonNull types:
annotated
annotated type
type bound
bound
–
class MyGenericClass1<T extends @NonNull Object>
–
legal substitutes:
@NonNull Object, @NonNull String
–
illegal:
@Nullable Object
–
because @NonNull X <: @Nullable X
Admit only @Nullable types:
annotated
annotated type
type parameter
parameter
(declaration)
(declaration)
–
we can't say <T super @Nullable Object>
–
class MyGenericClass2<@Nullable T>
–
(interpreted as both upper and lower bound)
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 18
Puzzle 1
●
8
Legal or not?
@NonNullByDefault class Tricky<T> {
void foo(T t) {}
void test() { foo(null); }
Null
Nulltype
typemismatch
mismatch(type
(typeannotations):
annotations):
}
'null'
'null'isisnot
notcompatible
compatibleto
tothe
thefree
freetype
typevariable
variable'T'
'T'
–
where does @NonNullByDefault apply
●
type parameter?
–
●
no
method parameter?
–
–
...
...
Wildcards
Wildcards and
and the
the use
use of
of type
type variables
variables
are
always
excluded
from
NonNullByDefault.
are always excluded from NonNullByDefault.
generally yes
but not to a type variable
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 19
Puzzle 2
●
8
What is this?
@NonNullByDefault class Tricky<T> {
void foo(@Nullable T t) {}
void test() { foo(null); }
}
●
“You said 'T' could mean anything”
–
so what is @Nullable T ?
●
–
e.g., if T := @NonNull String ?
the @Nullable variant of whatever T represents
●
e.g., @Nullable String
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
# 20
DEMO
●
Double Inference
●
External Annotations
Stephan Herrmann: A Deep Dive into the Void - EclipseCon Europe 2014
8
# 21