Chapter 1 -- UsingAndAvoidingNull
"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值, 如果这个值不存在,则返回指定的默认值
|
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的更多相关文章
- Modern C++ CHAPTER 2(读书笔记)
CHAPTER 2 Recipe 2-1. Initializing Variables Recipe 2-2. Initializing Objects with Initializer Lists ...
- Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- ApiWrapper
前面两片文章讲解了通过AIDL和Messenger两种方式实现Android IPC.而本文所讲的并不是第三种IPC方式,而是对前面两种方式进行封装,这样我们就不用直接把Aidl文件,java文件拷贝 ...
- Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger
Messenger类实际是对Aidl方式的一层封装.本文只是对如何在Service中使用Messenger类实现与客户端的通信进行讲解,对Messenger的底层不做说明.阅读Android Prog ...
- [转]第四章 使用OpenCV探测来至运动的结构——Chapter 4:Exploring Structure from Motion Using OpenCV
仅供参考,还未运行程序,理解部分有误,请参考英文原版. 绿色部分非文章内容,是个人理解. 转载请注明:http://blog.csdn.net/raby_gyl/article/details/174 ...
- 《深入理解计算机系统》 Chapter 7 读书笔记
<深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...
- 《Linux内核设计与实现》Chapter 3 读书笔记
<Linux内核设计与实现>Chapter 3 读书笔记 进程管理是所有操作系统的心脏所在. 一.进程 1.进程就是处于执行期的程序以及它所包含的资源的总称. 2.线程是在进程中活动的对象 ...
- PRML Chapter 2. Probability Distributions
PRML Chapter 2. Probability Distributions P68 conjugate priors In Bayesian probability theory, if th ...
- PRML Chapter 1. Introduction
PRML Chapter 1. Introduction 为了防止忘记,要把每章的重要内容都记下来,从第一章开始 2012@3@28 今天又回去稍微翻了一下第一章内容,发现第一次看的时候没有看透,每次 ...
- MathType 插入定义的chapter and section break后无法隐藏
每一章标题后面插入一个“Next Section Break”,这样定稿后各章文件组合为总文件后,方程编号会自动递增,如果已经插入了默认的“Equation Chapter 1 Section 1”, ...
随机推荐
- 【Java】链表中存储对象的问题
更新: 在一次搜索“变量声明在循环体内还是循环体外”问题时,碰见了一个这样的代码,与本文类似,代码如下: Document [] old ......//这是数据源 EntityDocument[] ...
- 使用php mcrypt加密解密
数字签名:对数据和私钥进行hash运算得到消息摘要,连同消息本身一块发给客户端.数据签名强调客户端接收到的数据是来自特定服务端,服务端具有对数据不可否认性.客户端通过确认此次签名的正确性来判断拿到的消 ...
- 浅谈Spring的AOP实现-代理机制
说起Spring的AOP(Aspect-Oriented Programming)面向切面编程大家都很熟悉(Spring不是这次博文的重点),但是我先提出几个问题,看看同学们是否了解,如果了解的话可以 ...
- Java 持久化之 -- IO 全面整理(看了绝不后悔)
目录: 一.java io 概述 什么是IO? IO包括输入流和输出流,输入流指的是将数据以字符或者字节形式读取到内存 分为字符输入流和字符输入流 输入流指的是从内存读取到外界 ,分为字符输入流和字节 ...
- 数据包注入重放工具aireplay-ng
数据包注入重放工具aireplay-ng aireplay-ng是aircrack-ng组件包的一个工具.它可以注入和重放数据帧,用于后期的WEP.WPA-PSK破解.它提供九种攻击模式,包括死亡 ...
- 【bzoj 1076】【SCOI2008】奖励关
1076: [SCOI2008]奖励关 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1602 Solved: 891[Submit][Status ...
- no acceptable C compiler found in $PATH
安装gcc编译器 yum install -y gcc 参考: http://blog.51cto.com/raulkang/573151
- ARM JTAG 20P to Cortex JTAG 10P
- 得到Revit子窗体
start /// <summary> /// 得到主窗体句柄 /// </summary> /// <returns></returns> publi ...
- WebLogic使用总结(四)——WebLogic部署Web应用
一.打包Web应用 首先将要部署到WebLogic的Web应用打包成war包,具体操作步骤如下图所示: 选中要打包的[oams]项目→[Export...]