"Null sucks." -Doug Lea

"Null 很恶心!"

"I call it my billion-dollar mistake." - Sir C. A. R. Hoare, on his invention of the null reference

"我称它为我的十亿美元错误"

Using and avoiding null 使用和避免null

Careless use of null can cause a staggering variety of bugs. Studying the Google code base, we found that something like 95% of collections weren't supposed to have any null values in them, and having those fail fast rather than silently accept null would have been helpful to developers.

不小心的使用null可能会造成令人吃惊的各种各样的bug.学习Google的代码基础,我们发现95%的collections不支持任何的null值,并且使用fail-fast机制而不是默默地接受null对开发者会更有帮助.

Additionally, null is unpleasantly ambiguous. It's rarely obvious what a null return value is supposed to mean -- for example, Map.get(key) can return null either because the value in the map is null, or the value is not in the map. Null can mean failure, can mean success, can mean almost anything. Using something other than null makes your meaning clear.

另外, null是非常有歧义的的一个东西.很难明确一个null返回值表示的是什么意思 -- 例如, Map.get(key) 会返回 null 可能因为value在map里是null, 也有可能是value根本不在map里. null可以代表事变,也可以代表成功,可以代表任何意思. 使用其他东西来代替null会是你的表意更清晰.

That said, there are times when null is the right and correct thing to use. null is cheap, in terms of memory and speed, and it's unavoidable in object arrays. But in application code, as opposed to libraries, it is a major source of confusion, difficult and weird bugs, and unpleasant ambiguities -- e.g. when Map.get returns null, it can mean the value was absent, or the value was present and null. Most critically, null gives no indication what a null value means.

即便如此,有时候null还是有必要使用的.null在内存和速度方面成本低,并且在对象数组中是不可避免的.但是在程序代码中,与类库截然相反,他确实造成迷惑, bug 和 歧义的主要原因 -- 例如, 当Map.get 返回null, 他可能表示value缺失, 也有可能表示 value就是null.最重要的是, null没有任何迹象可以表明一个null值是什么意思.

For these reasons, many of Guava's utilities are designed to fail fast in the presence of null rather than allow nulls to be used, so long as there is a null-friendly workaround available. Additionally, Guava provides a number of facilities both to make using null easier, when you must, and to help you avoid using null.

由于这些原因,许多Guava的工具类只要有null-friendly的解决方案, 就设计成了fail-fast机制而不是直接使用null.另外,Guava在你必须使用null的时候提供了一系列的工具来使null用起来更简单并帮助你避免使用null.

Specific Cases 特殊类

If you're trying to use null values in a Set or as a key in a Map -- don't; it's clearer (less surprising) if you explicitly special-case null during lookup operations.

假如你想在set中使用null值或者把null作为map的key -- 别这么做;  如果你在查询操作中明确使用null的特殊情况会跟清晰.

If you want to use null as a value in a Map -- leave out that entry; keep a separate Set of non-null keys (or null keys). It's very easy to mix up the cases where a Map contains an entry for a key, with value null, and the case where the Map has no entry for a key. It's much better just to keep such keys separate, and to think about what it means to your application when the value associated with a key is null.

如果你想在map中使用null -- 别考虑entry; 保持一个分离的non-null key的set(或者null key). 一个map包含一个null的key和一个map不包含这个key这两种情况是非常容易弄混的. 最好是保持这样的keys被隔离, 考虑清楚你的key是null到底表示什么意思.

If you're using nulls in a List -- if the list is sparse, might you rather use a Map<Integer, E>? This might actually be more efficient, and could potentially actually match your application's needs more accurately.

假如你在List中使用null -- 假如这个list是稀疏的, 你最好用一个 Map<Integer, E> 这样会更高效, 而且能更精准地匹配你的程序的需求.

Consider if there is a natural "null object" that can be used. There isn't always. But sometimes. For example, if it's an enum, add a constant to mean whatever you're expecting null to mean here. For example, java.math.RoundingMode has an UNNECESSARY value to indicate "do no rounding, and throw an exception if rounding would be necessary."

想象一下有一个自然的"null object"可能被使用. 例如, 假如是个enum, 添加一个常量来表示你想表示的null.例如, java.math.RoundingMode 有一个 UNNECESSARY 值用来表示 "不要四舍五入, 并且如果需要四舍五入会抛出一个异常"

If you really need null values, and you're having problems with a null-hostile collection implementations, use a different implementation. For example, use Collections.unmodifiableList(Lists.newArrayList()) instead of ImmutableList.

如果你真得需要null, 你会在null-hostile(null不友好)的集合实现遇到问题, 所以使用一个不一样的的实现吧. 例如, 使用 Collections.unmodifiableList(Lists.newArrayList())替代ImmutableList

Optional

Many of the cases where programmers use null is to indicate some sort of absence: perhaps where there might have been a value, there is none, or one could not be found. For example, Map.get returns null when no value is found for a key.

在许多情况下程序使用null是为了表示某种意义上的absence(缺失): 可能有一个值,但他是空的,也有可能这个值未找到. 例如, Map.get 当没有找到这个key的时候会返回 null.

Optional<T> is a way of replacing a nullable T reference with a non-null value. An Optional may either contain a non-null T reference (in which case we say the reference is "present"), or it may contain nothing (in which case we say the reference is "absent"). It is never said to "contain null."

Optional<T> 是一种使用non-null value替代nullable T 引用的方法. 一个 Optional 可能包含一个non-null T 引用(这种情况我们称reference是"present"(存在的)), 或者可能什么也不包含(这种情况我们称reference是"absent"(缺失的)).我们从不会说"包含 null".

Optional<Integer> possible =Optional.of(5);
possible.isPresent();// returns true
possible.get();// returns 5

Optional is not intended as a direct analogue of any existing "option" or "maybe" construct from other programming environments, though it may bear some similarities.

Optional 不打算直接模拟其他编程环境中的已存在的任何"option"或"maybe",虽然他们存在一些共同点.

We list some of the most common Optional operations here.

下面列举了一些最常用的Optional操作

Making an Optional 创建一个Optional

Each of these are static methods on Optional.

Optional.of(T)

Make an Optional containing the given non-null value, or fail fast on null.

创建一个包含给定非null值的Optional,如果给定值是null则使用fail fast机制抛出异常

Optional.absent()

Return an absent Optional of some type.

返回某个类型的absent  Optional

Optional.fromNullable(T)

Turn the given possibly-null reference into an Optional, treating non-null as present and null as absent.

将一个可能为null的refernce放入Optional, 将非null当做present, null当做absent

Query methods 查询方法

Each of these are non-static methods on a particular Optional<T> value.

这些方法都是特定的 Optional<T> 实例的非静态方法

boolean isPresent()

Returns true if this Optional contains a non-null instance.

返回 true 如果这个Optional包含一个non-null实例

T get()

Returns the contained T instance, which must be present; otherwise, throws an IllegalStateException.

返回包含的T实例, T必须是present的;否则,抛出 IllegalStateException

T or(T)

Returns the present value in this Optional, or if there is none, returns the specified default.

返回Optional中的present值, 如果这个值不存在,则返回指定的默认值

  • 如果是 Absent 实例, or(Object defaultValue) 返回 defaultValue
  • 如果是 Present 实例, or(T defaultValue) 返回 present value
T orNull()

Returns the present value in this Optional, or if there is none, returns null. The inverse operation of fromNullable.

返回 present value, 如果没有 present value, 则返回 null, 这是 fromNullable 的逆向操作

Set<T> asSet()

Returns an immutable singleton Set containing the instance in this Optional, if there is one, or otherwise an empty immutable set.

如果存在present value则返回一个不可变的单例的包含这个Optional的Set, 否则返回一个空的 immutable set

Optional provides several more handy utility methods besides these; consult the Javadoc for details.

Optional 提供了更多便利工具方法; 详情请查阅 Javadoc

What's the point? 这么做的意义是什么?

Besides the increase in readability that comes from giving null a name, the biggest advantage of Optional is its idiot-proof-ness. It forces you to actively think about the absent case if you want your program to compile at all, since you have to actively unwrap the Optional and address that case. Null makes it disturbingly easy to simply forget things, and though FindBugs helps, we don't think it addresses the issue nearly as well.

给予null一个名字除了提高可读性, Optional 最大的优势是它的"防误操作性"(idiot-proof-ness).如果你想你的程序编译通过,他强制你主动的去思考absent的情况, 因为你需要主动去展开Optional并解决absent的情况. Null使得它非常容易忽略一些事情, 即使FindBugs可以帮助我们,我们也认为它对解决这个问题有很好的效果.

This is especially relevant when you're returning values that may or may not be "present." You (and others) are far more likely to forget thatother.method(a, b) could return a null value than you're likely to forget that a could be null when you're implementing other.method. ReturningOptional makes it impossible for callers to forget that case, since they have to unwrap the object themselves for their code to compile.

这跟你的返回值是或不是"present"是息息相关的.你更大的可能是忘了 other.method(a,b) 会返回一个null值,而不是当你实现other.method的时候忘记 a 可能是null. 返回 Optional 使调用者不可能忘记返回值是null这种情况,因为他们必须展开这个Optional才能让代码通过编译

Convenience methods 便利方法

Whenever you want a null value to be replaced with some default value instead, use Objects.firstNonNull(T, T). As the method name suggests, if both of the inputs are null, it fails fast with a NullPointerException. If you are using an Optional, there are better alternatives -- e.g. first.or(second).

无论什么时候你想用一些默认值代替一个null值, 请使用 Objects.firstNonNull(T, T). 正如这个方法的名字建议的, 加入两个参数都是null, 他会进入fails fast机制抛出NullPointerException. 如果你使用Optional,则有更好的替代方法 -- 例如, first.or(second).

A couple of methods dealing with possibly-null String values are provided in Strings. Specifically, we provide the aptly named:

Strings提供了几个处理可能为null的String的方法. 我们专门为他们提供了合适的命名

emptyToNull(String)
isNullOrEmpty(String)
nullToEmpty(String)

We would like to emphasize that these methods are primarily for interfacing with unpleasant APIs that equate null strings and empty strings. Every time you write code that conflates null strings and empty strings, the Guava team weeps. (If null strings and empty strings mean actively different things, that's better, but treating them as the same thing is a disturbingly common code smell.)

强调一下,这些方法主要是用来替代那些令人不爽的吧null和""的String当做一样的东西的APIs的.每次你写代码吧null和"" String结合在一起,Guava团队都在哭泣.(如果null和"" String代表着完全不同的东西,那样还好,但是把他们看成是一样的东西这绝对还是普遍存在的代码问题)

最后是UserGuide里提到的方法示例

    public static void main(String[] args) {
// Present test
System.out.println("--- Present test ---");
Optional<String> present = Optional.of("Present Val");
System.out.println(present.get());
System.out.println(present.isPresent());
System.out.println(present.or("Default Value"));
System.out.println(present.orNull()); System.out.println(); // Absent test
System.out.println("--- Absent test ---");
Optional<String> absent = Optional.absent();
// throw IllegalStateException
// System.out.println(absent.get());
System.out.println(absent.isPresent());
System.out.println(absent.or("Default Value"));
System.out.println(absent.orNull()); System.out.println(); // dynamic Absent or Present Optional
System.out.println("--- dynamic Absent or Present Optional ---");
Optional<String> dynamic1 = Optional.fromNullable("None-Null"); // equals to Option.of("None-Null")
Optional<String> dynamic2 = Optional.fromNullable(null); // equals to Option.absent()
System.out.println(dynamic1.isPresent());
System.out.println(dynamic2.isPresent()); System.out.println(); // Objects.firstNonNull() test
System.out.println("--- Objects.firstNonNull() test ---");
System.out.println(Objects.firstNonNull(null, "None-Null")); System.out.println(); // Strings convenience method test
System.out.println("--- Strings convenience method test ---");
String[] strArr = { null, "", "None-Null" };
for (String str : strArr) {
System.out.println(Strings.emptyToNull(str));
System.out.println(Strings.isNullOrEmpty(str));
System.out.println(Strings.nullToEmpty(str));
}
}

Output

--- Present test ---
Present Val
true
Present Val
Present Val --- Absent test ---
false
Default Value
null --- dynamic Absent or Present Optional ---
true
false --- Objects.firstNonNull() test ---
None-Null --- Strings convenience method test ---
null
true null
true None-Null
false
None-Null

Chapter 1 -- UsingAndAvoidingNull的更多相关文章

  1. Modern C++ CHAPTER 2(读书笔记)

    CHAPTER 2 Recipe 2-1. Initializing Variables Recipe 2-2. Initializing Objects with Initializer Lists ...

  2. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- ApiWrapper

    前面两片文章讲解了通过AIDL和Messenger两种方式实现Android IPC.而本文所讲的并不是第三种IPC方式,而是对前面两种方式进行封装,这样我们就不用直接把Aidl文件,java文件拷贝 ...

  3. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger

    Messenger类实际是对Aidl方式的一层封装.本文只是对如何在Service中使用Messenger类实现与客户端的通信进行讲解,对Messenger的底层不做说明.阅读Android Prog ...

  4. [转]第四章 使用OpenCV探测来至运动的结构——Chapter 4:Exploring Structure from Motion Using OpenCV

    仅供参考,还未运行程序,理解部分有误,请参考英文原版. 绿色部分非文章内容,是个人理解. 转载请注明:http://blog.csdn.net/raby_gyl/article/details/174 ...

  5. 《深入理解计算机系统》 Chapter 7 读书笔记

    <深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...

  6. 《Linux内核设计与实现》Chapter 3 读书笔记

    <Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...

  7. PRML Chapter 2. Probability Distributions

    PRML Chapter 2. Probability Distributions P68 conjugate priors In Bayesian probability theory, if th ...

  8. PRML Chapter 1. Introduction

    PRML Chapter 1. Introduction 为了防止忘记,要把每章的重要内容都记下来,从第一章开始 2012@3@28 今天又回去稍微翻了一下第一章内容,发现第一次看的时候没有看透,每次 ...

  9. MathType 插入定义的chapter and section break后无法隐藏

    每一章标题后面插入一个“Next Section Break”,这样定稿后各章文件组合为总文件后,方程编号会自动递增,如果已经插入了默认的“Equation Chapter 1 Section 1”, ...

随机推荐

  1. 高能天气——团队Scrum冲刺阶段-Day 6

    高能天气--团队Scrum冲刺阶段-Day 6 今日完成任务 于欣月:完善计步器功能:实现了历史步数统计和设置锻炼计划功能,并实现可视化图形界面 余坤澎:将闹钟部分和小游戏部分进行了合并 康皓越:配合 ...

  2. 001.VNC介绍

    一 VNC介绍 VNC 服务是一个自由开源软件,采用RFB通信协议.RFB ("remote 帧缓存 ") 是一个远程图形用户的简单协议,因为它工作在帧缓存级别上,所以它可以应用于 ...

  3. 跟厂长学PHP7内核(五):系统分析生命周期

    上篇文章讲述了模块初始化阶段之前的准备工作,本篇我来详细介绍PHP生命周期的五个阶段. 一.模块初始化阶段 我们先来看一下该阶段的每个函数的作用. 1.1.sapi_initialize_reques ...

  4. 命令:tr

    参考资料:https://www.thegeekstuff.com/2012/12/linux-tr-command/ 简介 tr命令用于转换.删除或者去除重复字符.它从STDIN中读取数据并且将其写 ...

  5. HTTP错误405

    405 - 用来访问本页面的(方法不被允许) HTTP 错误 405 -禁止访问资源 HTTP 错误 405 405 不允许此方法 对于请求所标识的资源,不允许使用请求行中所指定的方法.请确保为所请求 ...

  6. 开源的在线评测系统——Vakuum

    项目地址 http://code.google.com/p/vakuum-oj/ https://github.com/BYVoid/vakuum 简介 Vakuum是一个基于Linux+PHP的在线 ...

  7. 吴恩达-coursera-机器学习-week10

    十七.大规模机器学习(Large Scale Machine Learning) 17.1 大型数据集的学习 17.2 随机梯度下降法 17.3 小批量梯度下降 17.4 随机梯度下降收敛 17.5 ...

  8. 喵哈哈村的魔法考试 Round #7 (Div.2) 题解

    喵哈哈村的魔法考试 Round #7 (Div.2) 注意!后四道题来自于周日的hihocoder offer收割赛第九场. 我建了个群:欢迎加入qscoj交流群,群号码:540667432 大概作为 ...

  9. Xcode6 iOS7模拟器和Xcode7 iOS8模拟器离线下载

    Xcode6 只支持iOS7和iOS8的模拟器 Xcode7 只支持iOS9和iOS8的模拟器 Xcode 并不会识别 SDKs 目录下的模拟器,我经过一些尝试以后,发现要放在这个目录下: /Libr ...

  10. THE TOOLS TO MANAGE YOUR DATA ACROSS CLOUDS

    http://blog.grexit.com/manage-data-across-clouds/ That the average small business uses a cloud servi ...