int main() {
int n;
// possibly more code
n = foo();
}
int main() {
int n = 0;
// possibly more code
n = foo();
}
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. -- C.A.R Hoare
When someone thought of implementing that idea in OO...
public class LinkedList<T> {
private class Node {
private T value;
private Node next = null;
public Node(T value) {
this.value = value;
}
}
private Node head = null;
private Node last = null;
public void add(T value) {
Node temp = last;
Node node = new Node(value);
last = node;
if (head == null) {
head = node;
} else {
temp.next = node;
}
}
}
public class LinkedList<T> {
private Node NIL = new Node();
private class Node {
private T value;
private Node next = null;
private boolean isEmpty;
public Node(T value) {
this.value = value;
isEmpty = false;
next = NIL;
}
public Node() {
isEmpty = true;
}
}
private Node head = NIL;
private Node last = NIL;
public void add(T value) {
Node temp = last;
Node node = new Node(value);
last = node;
if (head.isEmpty) {
head = node;
} else {
temp.next = node;
}
}
}
V Map::get(Object key)
Returns the value to which the specified
key is mapped, or null if this map
contains no mapping for the key.
factory.getFoo().getProperty("bar").getString();
...what about nulls?
public class LinkedList<T> {
private Node NIL = new Node();
private class Node {
private T value;
private Node next = null; // I'm null but nobody will ever know :)
private boolean isEmpty;
public Node(T value) {
this.value = value;
isEmpty = false;
next = NIL;
}
public Node() {
isEmpty = true;
}
}
private Node head = NIL;
private Node last = NIL;
public void add(T value) {
Node temp = last;
Node node = new Node(value);
last = node;
if (head.isEmpty) {
head = node;
} else {
temp.next = node;
}
}
}
This could be the Programming Community when we all
agree to use null just as an implementation detail!
Don't accept null arguments in methods
void doIt(Foo foo, Bar bar) {
if (bar == null) {
// do this
} else {
// something else
}
}
doIt(foo, null);
doIt(foo);
doItWithABar(foo, bar);
void doIt(Foo foo) {
Bar bar = giveMeADefaultBar();
doItWithABar(foo, bar);
}
// code
Bar bar = service.getIt();
doIt(foo, bar);
void doIt(Foo foo, Bar bar) {
if (bar == null) { // y'know because null happens!
// code that doesn't use bar
} else {
// code that use it
}
}
// code
Bar bar = service.getIt();
doIt(foo, bar);
void doIt(Foo foo, Bar bar) {
java.util.Objects.requireNonNull(foo);
java.util.Objects.requireNonNull(bar);
// more code
}
Objects is part of the Java API
since 1.7. Can't use that version?
Use Guava Preconditions!
Basz(Foo foo) {
this.foo = Objects.requireNonNull(foo);
// more code
}
Never return null
String getValueOrElse(Foo foo, String defaultValue) {
// code
String value = ...; // I calculate the vale somehow
return value != null ? value : defaultValue;
}
Java 8 introduced a getOrDefault method in the Map interface
List<Foo> getFoos() {
// code
List<Foo> foos = ...; // Get the list of foos
return foos.size > 0 ? foos : Collections.emptyList();
}
public void run() throws IOException {
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(source)) {
for (Path path : directoryStream) {
if (Images.isImage(path)) {
Image image = new Image(path);
if (image.isProportional(width, height)) {
image = image.resize(width, height);
image.write(destination);
}
}
}
}
}
public void run() throws IOException {
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(source)) {
for (Path path : directoryStream) {
Optional.of(path)
.filter(Images::isImage)
.map(Image::of)
.filter(image -> image.isProportial(width, height))
.map(image -> image.resize(width, height))
.forEach(Image::write);
}
}
}
Optional<Foo> getFoo() {
// code
}
public Foo getFoo(Bar bar) {
Foo foo = null;
try {
foo = bar.something();
} catch (MyException e) {
LOGGER.error();
}
return foo;
}
ByteArrayOutputStream outputStream = null;
// this need to be visible...
GZIPOutputStream gzipOutputStream = null;
try {
outputStream = new ByteArrayOutputStream();
gzipOutputStream = new GZIPOutputStream(outputStream);
gzipOutputStream.write(data);
return outputStream.toByteArray();
catch (Exception e) {
// error handling
} finally {
if (gzipOutputStream != null) {
gzipOutputStream.close(); // ...here!!
}
}
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream =new GZIPOutputStream(outputStream)) {
gzipOutputStream.write(data);
return outputStream.toByteArray();
catch (Exception e) {
// error handling
}
void something() {
Foo foo = getFoo(); // this throws an exception
}
void something() {
Foo foo = null;
try {
foo = getFoo(); // this throws an exception
} catch (MyException e) {
}
}
void doIt() {
try { // no code before
} catch (MyException e) {
} // no code after
}
Foo getFoo(Bar bar) {
try {
Foo foo = bar.something();
return foo;
} catch (MyException e) {
throw new AssertionError(e);
}
}
Optional<Foo> getFoo(Bar bar) {
try {
Foo foo = bar.something();
return Optional.of(foo);
} catch (MyException e) {
return Optional.empty();
}
}
void doIt(Bar bar) {
try {
Foo foo = bar.something();
foo.amazeMe();
} catch (MyException e) {
LOGGER.info("This failed");
}
}
Foo getFoo(Bar bar) throws MyException {
Foo foo = bar.something();
return foo;
}
Never instantiate to null
Foo something = null;
if (/* a contional */) {
something = ...;
} else {
// complex code
something = ...;
}
// code that uses something
Foo something = /* a contional */ ? value 1 : value 2;
// code that uses something
Foo something = /* a contional */ ? value 1 : get();
// code that uses something
Foo something = get();
* * *
Foo get() {
if (/* a conditional */) {
return value 1;
}
// complex code to calculate value
return value 2
}
public T fullMonty() {
T obj = null;
try {
// code
} catch (ABCException e) {
// code
}
return obj;
}
public T fullMonty(/* params */) {
try {
return doFullMonty(/* params */);
} catch (ABCException e) {
// error handling code
// here you have visibility
// of all params
}
}
private T doFullMonty(/* params */) throws ABCException {
// simple code
return tValue;
}
public T fullMonty() {
T obj = null;
try {
// code
} catch (ABCException e) {
// code
}
return obj;
}
public Optional<T> fullMonty(Bar bar) {
try {
return Optional.of(doFullMonty(bar));
} catch (ABCException e) {
LOGGER.error("Full monty failed on {}", bar);
return Optional.empty();
}
}
private T doFullMonty(Bar bar) throws ABCException {
// easy to understand code
return tValue;
}
String line = null;
while ((line = br.readLine()) != null) {
// do something with line
}
String line = br.readLine();
while (line != null) {
// do something with line
line = br.readLine();
}