eclipse快速使用指南_快速彻底的“空”指南:它是什么,以及如何使用它

eclipse快速使用指南

by Christian Neumanns

克里斯蒂安·纽曼斯(Christian Neumanns)

快速彻底的“ null ”指南:它是什么,以及如何使用它 (A quick and thorough guide to ‘null’: what it is, and how you should use it)

What is the meaning of null? How is null implemented? When should you use null in your source code, and when should you not use it?

null的含义是什么? 如何实现null ? 当你应该使用null在你的源代码,你应该什么时候使用它呢?

介绍 (Introduction)

null is a fundamental concept in many programming languages. It is ubiquitous in all kinds of source code written in these languages. So it is essential to fully grasp the idea of null . We have to understand its semantics and implementation, and we need to know how to use null in our source code.

null是许多编程语言中的基本概念。 用这些语言编写的各种源代码中无处不在。 因此,充分掌握null的概念至关重要。 我们必须了解其语义和实现,并且需要了解如何在源代码中使用null

Comments in programmer forums sometimes reveal a bit of confusion with null. Some programmers even try to completely avoid null. Because they think of it as the 'million-dollar mistake', a term coined by Tony Hoare, the inventor of null.

程序员论坛中的注释有时会显示对null的混淆。 一些程序员甚至试图完全避免null 。 因为他们将其视为“百万美元的错误”,这是null的发明者Tony Hoare创造的一个术语。

Here is a simple example: Suppose that Alice’s email_address points to null. What does this mean? Does it mean that Alice doesn't have an email address? Or that her email address is unknown? Or that it is secret? Or does it simply mean that email_address is 'undefined' or 'uninitialized'? Let's see. After reading this article, everybody should be able to answer such questions without hesitation.

这是一个简单的示例:假设Alice的email_address指向null 。 这是什么意思? 这是否意味着Alice没有电子邮件地址? 还是她的电子邮件地址未知? 还是那是秘密? 还是仅表示email_address为“未定义”或“未初始化”? 让我们来看看。 阅读本文之后,每个人都应该能够毫不犹豫地回答这些问题。

Note: This article is programming-language-neutral — as far as possible. Explanations are general and not tied to a specific language. Please consult your programming language manuals for specific advice on null. However, this article contains some simple source code examples shown in Java. But it’s not difficult to translate them into your favorite language.

注意:本文是与编程语言无关的—尽可能。 解释是一般性的,与特定语言无关。 请参考您的编程语言手册以获取有关null特定建议。 但是,本文包含一些用Java显示的简单源代码示例。 但是将它们翻译成您喜欢的语言并不难。

运行时实施 (Run-time Implementation)

Before discussing the meaning of null, we need to understand how null is implemented in memory at run-time.

在讨论null的含义之前,我们需要了解运行时如何在内存中实现null

Note: We will have a look at a typical implementation of null. The actual implementation in a given environment depends on the programming language and target environment, and might differ from the implementation shown here.

注意:我们将看一下null典型实现。 给定环境中的实际实现取决于编程语言和目标环境,并且可能与此处所示的实现不同。

Suppose we have the following source code instruction:

假设我们有以下源代码指令:

String name = "Bob";

Here we declare a variable of type String and with the identifier name that points to the string "Bob".

在这里,我们声明一个String类型的变量,其标识符name指向字符串"Bob"

Saying “points to” is important in this context, because we are assuming that we work with reference types (and not with value types). More on this later.

在这种情况下,说“指向”很重要,因为我们假设我们使用引用类型 (而不是值类型 )。 稍后再详细介绍。

To keep things simple, we will make the following assumptions:

为简单起见,我们将进行以下假设:

  • The above instruction is executed on a 16-bits CPU with a 16-bits address space.

    上面的指令在具有16位地址空间的16位CPU上执行。
  • Strings are encoded as UTF-16. They are terminated with 0 (as in C or C++).

    字符串编码为UTF-16。 它们以0终止(如C或C ++)。

The following picture shows an excerpt of the memory after executing the above instruction:

下图显示了执行上述指令后的内存摘录:

The memory addresses in the above picture are chosen arbitrarily and are irrelevant for our discussion.

上图中的存储器地址是任意选择的,与我们的讨论无关。

As we can see, the string "Bob" is stored at address B000 and occupies 4 memory cells.

如我们所见,字符串"Bob"存储在地址B000处,并占用4个存储单元。

Variable name is located at address A0A1. The content of A0A1 is B000, which is the starting memory location of the string "Bob". That's why we say: The variable name points to "Bob".

变量name位于地址A0A1。 A0A1的内容是B000,它是字符串"Bob"的起始存储位置。 这就是为什么我们说:变量name 指向 "Bob"

So far so good.

到目前为止,一切都很好。

Now suppose that, after executing the above instruction, you execute the following:

现在假设执行上述指令后,执行以下操作:

name = null;

Now name points to null.

现在name指向null

And this is the new state in memory:

这是内存中的新状态:

We can see that nothing has changed for the string "Bob" which is still stored in memory.

我们可以看到,仍然存储在内存中的字符串"Bob"没有任何变化。

Note: The memory needed to store the string "Bob" might later be released if there is a garbage collector and no other reference points to "Bob", but this is irrelevant in our discussion.

注意:如果存在垃圾收集器且没有其他指向"Bob"引用,则稍后可能会释放存储字符串"Bob"所需的内存,但这与我们的讨论无关。

What’s important is that the content of A0A1 (which represents the value of variable name) is now 0000. So, variable name doesn't point to "Bob" anymore. The value 0 (all bits at zero) is a typical value used in memory to denote null. It means that there is no value associated with name. You can also think of it as the absence of data or simply no data.

重要的是A0A1的内容(代表变量name的值)现在为0000。因此,变量name不再指向"Bob" 。 值0(所有位均为零)是在内存中用于表示null的典型值。 这意味着没有与name相关联的值 。 您也可以将其视为缺少数据或根本就没有数据

Note: The actual memory value used to denote null is implementation-specific. For example the Java Virtual Machine Specification states at the end of section 2.4. “Reference Types and Values:”

注意:用于表示null的实际内存值是特定于实现的。 例如,《 Java虚拟机规范》在第2.4节的末尾声明 参考类型和值:”

The Java Virtual Machine specification does not mandate a concrete value encoding null.

Java虚拟机规范没有规定编码null的具体值。

Remember:

记得:

If a reference points to null, it simply means that there is no value associated with it.

如果引用指向null ,则仅表示存在 没有相关的价值

Technically speaking, the memory location assigned to the reference contains the value 0 (all bits at zero), or any other value that denotes null in the given environment.

从技术上讲,分配给引用的内存位置包含值0(所有位均为零),或在给定环境中表示null值的任何其他值。

性能 (Performance)

As we learned in the previous section, operations involving null are extremely fast and easy to perform at run-time.

正如我们在上一节中了解到的那样,涉及null操作非常快且易于在运行时执行。

There are only two kinds of operations:

只有两种操作:

  • Initialize or set a reference to null (e.g. name = null): The only thing to do is to change the content of one memory cell (e.g. setting it to 0).

    初始化或设置对null的引用(例如name = null ):唯一要做的就是更改一个存储单元的内容(例如将其设置为0)。

  • Check if a reference points to null (e.g. if name == null): The only thing to do is to check if the memory cell of the reference holds the value 0.

    检查引用是否指向null (例如, if name == null ):唯一要做的就是检查引用的存储单元是否保持值为0。

Remember:

记得:

Operations on null are exceedingly fast and cheap.

null进行操作非常快速且便宜。

引用与值类型 (Reference vs Value Types)

So far we assumed working with reference types. The reason for this is simple: null doesn't exist for value types.

到目前为止,我们假定使用引用类型 。 原因很简单: 值类型不存在null

Why?

为什么?

As we have seen previously, a reference is a pointer to a memory-address that stores a value (e.g. a string, a date, a customer, whatever). If a reference points to null, then no value is associated with it.

如前所述,引用是指向存储值(例如字符串,日期,客户等)的内存地址的指针 。 如果引用指向null ,则没有任何值与之关联。

On the other hand, a value is, by definition, the value itself. There is no pointer involved. A value type is stored as the value itself. Therefore the concept of null doesn't exist for value types.

另一方面,根据定义,值就是值本身。 没有涉及指针。 值类型存储为值本身。 因此,对于值类型不存在null的概念。

The following picture demonstrates the difference. On the left side you can see again the memory in case of variable name being a reference pointing to "Bob". The right side shows the memory in case of variable name being a value type.

下图演示了差异。 如果变量name是指向“ Bob”的引用,则在左侧可以再次看到存储器。 右侧显示了在变量name为值类型的情况下的内存。

As we can see, in case of a value type, the value itself is directly stored at the address A0A1 which is associated with variable name.

如我们所见,在值类型的情况下,值本身直接存储在与变量name关联的地址A0A1处。

There would be much more to say about reference versus value types, but this is out of the scope of this article. Please note also that some programming languages support only reference types, others support only value types, and some (e.g. C# and Java) support both of them.

关于引用与值类型还有更多的话要说,但这不在本文的讨论范围之内。 另请注意,某些编程语言仅支持引用类型,其他编程语言仅支持值类型,而某些语言(例如C#和Java)均支持它们。

Remember:

记得:

The concept of null exists only for reference types. It doesn't exist for value types.

null的概念仅适用于引用类型。 对于值类型不存在。

含义 (Meaning)

Suppose we have a type person with a field emailAddress. Suppose also that, for a given person which we will call Alice, emailAddress points to null.

假设我们有一个类型为person的字段emailAddress 。 还假设,对于给定的我们将称为Alice的人, emailAddress指向null

What does this mean? Does it mean that Alice doesn’t have an email address? Not necessarily.

这是什么意思? 这是否意味着Alice没有电子邮件地址? 不必要。

As we have seen already, what we can assert is that no value is associated with emailAddress.

正如我们已经看到的,我们可以断言, 没有值与emailAddress关联

But why is there no value? What is the reason of emailAddress pointing to null? If we don't know the context and history, then we can only speculate. The reason for null could be:

但是为什么没有价值呢? emailAddress指向null的原因是什么? 如果我们不了解上下文和历史,那么我们只能推测。 null的原因可能是:

Alice doesn’t have an email address. Or…

爱丽丝没有电子邮件地址。 要么…

Alice has an email address, but:

爱丽丝有一个电子邮件地址,但是:

  • it has not yet been entered in the database

    它尚未输入数据库
  • it is secret (unrevealed for security reasons)

    这是秘密(出于安全原因未公开)
  • there is a bug in a routine that creates a person object without setting field emailAddress

    例程中有一个错误,该例程在不设置字段emailAddress情况下创建了人员对象

  • and so on.

    等等。

In practice we often know the application and context. We intuitively associate a precise meaning to null. In a simple and flawless world, null would simply mean that Alice actually doesn't have an email address.

在实践中,我们经常了解应用程序和上下文。 我们直观地将精确含义与null关联。 在一个简单而完美的世界中, null只是意味着Alice实际上没有电子邮件地址。

When we write code, the reason why a reference points to null is often irrelevant. We just check for null and take appropriate actions. For example, suppose that we have to write a loop that sends emails for a list of persons. The code (in Java) could look like this:

当我们编写代码, 之所以一个参考点,以null往往是无关紧要的。 我们只检查null并采取适当的措施。 例如,假设我们必须编写一个循环来发送电子邮件以获取人员列表。 代码(用Java)可能如下所示:

for ( Person person: persons ) {    if ( person.getEmailAddress() != null ) {        // code to send email    } else {        logger.warning("No email address for " + person.getName());    }}

In the above loop we don’t care about the reason for null. We just acknowledge the fact that there is no email address, log a warning, and continue.

在上面的循环中,我们不在乎null的原因。 我们只承认没有电子邮件地址,记录警告并继续的事实。

Remember:

记得:

If a reference points to null then it always means that there is no value associated with it.

如果引用指向null则始终表示存在 没有相关的价值

In most cases, null has a more specific meaning that depends on the context.

在大多数情况下, null具有取决于上下文更具体的含义

为什么它为null(Why is it null?)

Sometimes it is important to know why a reference points to null.

有时,重要的要知道引用为什么指向null

Consider the following function signature in a medical application:

在医疗应用程序中考虑以下功能签名:

List<Allergy> getAllergiesOfPatient ( String patientId )

In this case, returning null (or an empty list) is ambiguous. Does it mean that the patient doesn't have allergies, or does it mean that an allergy test has not yet been performed? These are two semantically very different cases that must be handled differently. Or else the outcome might be life-threatening.

在这种情况下,返回null (或空列表)是不明确的。 这是否意味着患者没有过敏React,还是意味着尚未进行过敏测试? 这是两种语义上非常不同的情况,必须以不同的方式处理。 否则结果可能会危及生命。

Just suppose that the patient has allergies, but an allergy test has not yet been done and the software tells the doctor that 'there are no allergies'. Hence we need additional information. We need to know why the function returns null.

只是假设患者有过敏,但尚未进行过敏测试,并且该软件告诉医生“没有过敏”。 因此,我们需要其他信息。 我们需要知道为什么函数返回null

It would be tempting to say: Well, to differentiate, we return null if an allergy test has not yet been performed, and we return an empty list if there are no allergies.

很有可能会说:好吧,要区分,如果尚未执行过敏测试,我们将返回null如果没有过敏,我们将返回一个空列表。

DON’T DO THIS!

不要这样做!

This is bad data design for multiple reasons.

由于多种原因,这是糟糕的数据设计。

The different semantics for returning null versus returning an empty list would need to be well documented. And as we all know, comments can be wrong (i.e. inconsistent with the code), outdated, or they might even be inaccessible.

返回null和返回空列表的不同语义将需要有据可查。 众所周知,注释可能是错误的(即与代码不一致),过时的,甚至可能无法访问。

There is no protection for misuses in client code that calls the function. For example, the following code is wrong, but it compiles without errors. Moreover, the error is difficult to spot for a human reader. We can’t see the error by just looking at the code without considering the comment of getAllergiesOfPatient:

在调用该函数的客户端代码中没有对滥用的保护。 例如,以下代码是错误的,但是可以正确编译。 此外,对于人类读者来说,很难发现该错误。 我们只看代码而不考虑getAllergiesOfPatient:的注释就看不到错误getAllergiesOfPatient:

List<Allergy> allergies = getAllergiesOfPatient ( "123" );				if ( allergies == null ) {    System.out.println ( "No allergies" );             // <-- WRONG!} else if ( allergies.isEmpty() ) {    System.out.println ( "Test not done yet" );        // <-- WRONG!} else {    System.out.println ( "There are allergies" );}

The following code would be wrong too:

以下代码也将是错误的:

List<Allergy> allergies = getAllergiesOfPatient ( "123" );if ( allergies == null || allergies.isEmpty() ) {    System.out.println ( "No allergies" );             // <-- WRONG!} else {    System.out.println ( "There are allergies" );}

If the null/empty-logic of getAllergiesOfPatient changes in the future, then the comment needs to be updated, as well as all client code. And there is no protection against forgetting any one of these changes.

如果将来getAllergiesOfPatientnull / empty-logic更改,则需要更新注释以及所有客户端代码。 并且没有防止忘记这些更改中的任何一项的保护措施。

If, later on, there is another case to be distinguished (e.g. an allergy test is pending — the results are not yet available), or if we want to add specific data for each case, then we are stuck.

如果以后要区分另一种情况(例如,过敏测试尚在进行中-结果尚不可用),或者如果我们想为每种情况添加特定数据,那么我们将陷入困境。

So the function needs to return more information than just a list.

因此,该函数需要返回的信息不仅仅是列表。

There are different ways to do this, depending on the programming language we use. Let’s have a look at a possible solution in Java.

有多种方法可以执行此操作,具体取决于我们使用的编程语言。 让我们看一下Java中可能的解决方案。

In order to differentiate the cases, we define a parent type AllergyTestResult, as well as three sub-types that represent the three cases (NotDone, Pending, and Done):

为了区分案例,我们定义了父类型AllergyTestResult ,以及代表三个案例的三个子类型( NotDonePendingDone ):

interface AllergyTestResult {}
interface NotDoneAllergyTestResult extends AllergyTestResult {}
interface PendingAllergyTestResult extends AllergyTestResult {    public Date getDateStarted();}
interface DoneAllergyTestResult extends AllergyTestResult {    public Date getDateDone();    public List<Allergy> getAllergies(); // null if no allergies                                         // non-empty if there are                                         // allergies}

As we can see, for each case we can have specific data associated with it.

如我们所见,对于每种情况,我们都可以拥有与之关联的特定数据。

Instead of simply returning a list, getAllergiesOfPatient now returns an AllergyTestResult object:

现在, getAllergiesOfPatient返回列表, getAllergiesOfPatient返回AllergyTestResult对象:

AllergyTestResult getAllergiesOfPatient ( String patientId )

Client code is now less error-prone and looks like this:

客户端代码现在不那么容易出错,看起来像这样:

AllergyTestResult allergyTestResult = getAllergiesOfPatient("123");
if (allergyTestResult instanceof NotDoneAllergyTestResult) {    System.out.println ( "Test not done yet" );   } else if (allergyTestResult instanceof PendingAllergyTestResult) {    System.out.println ( "Test pending" );   } else if (allergyTestResult instanceof DoneAllergyTestResult) {    List<Allergy> list = ((DoneAllergyTestResult)         allergyTestResult).getAllergies();    if (list == null) {        System.out.println ( "No allergies" );    } else if (list.isEmpty()) {        assert false;    } else {        System.out.println ( "There are allergies" );    }} else {    assert false;}

Note: If you think that the above code is quite verbose and a bit hard to write, then you are not alone. Some modern languages allow us to write conceptually similar code much more succinctly. And null-safe languages distinguish between nullable and non-nullable values in a reliable way at compile-time — there is no need to comment the nullability of a reference or to check whether a reference declared to be non-null has accidentally been set to null.

注意:如果您认为上面的代码很冗长并且很难编写,那么您并不孤单。 一些现代语言使我们可以更简洁地编写概念上相似的代码。 而且,空安全语言在编译时以可靠的方式区分了可空值和非空值–无需注释引用的可空性,也无需检查声明为非空的引用是否被意外设置为null

Remember:

记得:

If we need to know why there is no value associated with a reference, then additional data must be provided to differentiate the possible cases.

如果我们需要知道为什么没有与引用相关联的值,则必须提供其他数据来区分可能的情况

初始化 (Initialization)

Consider the following instructions:

请考虑以下说明:

String s1 = "foo";String s2 = null;String s3;

The first instruction declares a String variable s1 and assigns it the value "foo".

第一条指令声明一个String变量s1并为其分配值"foo"

The second instruction assigns null to s2.

第二条指令将s2分配为null

The more interesting instruction is the last one. No value is explicitly assigned to s3. Hence, it is reasonable to ask: What is the state of s3 after its declaration? What will happen if we write s3 to the OS output device?

最后一条指令是更有趣的指令。 没有值明确分配给s3 。 因此,有理由问: s3声明后的状态是什么? 如果将s3写入OS输出设备会发生什么?

It turns out that the state of a variable (or class field) declared without assigning a value depends on the programming language. Moreover, each programming language might have specific rules for different cases. For example, different rules apply for reference types and value types, static and non-static members of a class, global and local variables, and so on.

事实证明,声明的变量(或类字段)的状态不分配值取决于编程语言。 而且,每种编程语言对于不同的情况可能都有特定的规则。 例如,不同的规则适用于引用类型和值类型,类的静态和非静态成员,全局变量和局部变量,等等。

As far as I know, the following rules are typical variations encountered:

据我所知,以下规则是遇到的典型变化:

  • It is illegal to declare a variable without also assigning a value

    在不分配值的情况下声明变量是非法的
  • There is an arbitrary value stored in s3, depending on the memory content at the time of execution - there is no default value

    s3存储有一个任意值,具体取决于执行时的内存内容-没有默认值

  • A default value is automatically assigned to s3. In case of a reference type, the default value is null. In case of a value type, the default value depends on the variable’s type. For example 0 for integer numbers, false for a boolean, and so on.

    默认值自动分配给s3. 如果是引用类型,则默认值为null. 如果是值类型,则默认值取决于变量的类型。 例如, 0表示整数, false表示布尔值,依此类推。

  • the state of s3 is 'undefined'

    s3的状态为“未定义”

  • the state of s3 is 'uninitialized', and any attempt to use s3 results in a compile-time error.

    s3的状态为“未初始化”,并且任何使用s3尝试都会导致编译时错误。

The best option is the last one. All other options are error-prone and/or impractical — for reasons we will not discuss here, because this article focuses on null.

最好的选择是最后一个。 所有其他选项都是容易出错和/或不切实际的-由于本文将重点放在null上,因此我们不在此讨论这些原因。

As an example, Java applies the last option for local variables. Hence, the following code results in a compile-time error at the second line:

例如,Java将最后一个选项应用于局部变量。 因此,以下代码在第二行导致编译时错误:

String s3;System.out.println ( s3 );

Compiler output:

编译器输出:

error: variable s3 might not have been initialized

Remember:

记得:

If a variable is declared, but no explicit value is assigned to it, then it’s state depends on several factors which are different in different programming languages.

如果声明了变量,但未为其分配显式值, 则其状态取决于多种因素,这些因素在不同的编程语言中是不同的。

In some languages, null is the default value for reference types.

在某些语言中, null是引用类型的默认值。

何时使用null (何时不使用它) (When to Use null (And When Not to Use It))

The basic rule is simple: null should only be allowed when it makes sense for an object reference to have 'no value associated with it'. (Note: an object reference can be a variable, constant, property (class field), input/output argument, and so on.)

基本规则很简单:只有在对象引用具有“无关联值”的情况下才应允许使用null 。 (注意:对象引用可以是变量,常量,属性(类字段),输入/输出参数等。)

For example, suppose type person with fields name and dateOfFirstMarriage:

例如,假设型person与字段namedateOfFirstMarriage

interface Person {    public String getName();    public Date getDateOfFirstMarriage();}

Every person has a name. Hence it doesn’t make sense for field name to have 'no value associated with it'. Field name is non-nullable. It is illegal to assign null to it.

每个人都有名字。 因此,字段name没有“无关联值”是没有意义的。 字段name 不可为null 。 给它分配null是非法的。

On the other hand, field dateOfFirstMarriage doesn't represent a required value. Not everyone is married. Hence it makes sense for dateOfFirstMarriage to have 'no value associated with it'. Therefore dateOfFirstMarriage is a nullable field. If a person's dateOfFirstMarriage field points to null then it simply means that this person has never been married.

另一方面,字段dateOfFirstMarriage不代表必需的值。 不是每个人都结婚。 因此, dateOfFirstMarriage具有“无关联值”是有意义的。 因此, dateOfFirstMarriage空的字段。 如果某人的dateOfFirstMarriage字段指向null则仅表示该人从未结婚。

Note: Unfortunately most popular programming languages don’t distinguish between nullable and non-nullable types. There is no way to reliably state that null can never be assigned to a given object reference. In some languages it is possible to use annotations, such as the non-standard annotations @Nullable and @NonNullable in Java. Here is an example:

注意:不幸的是,大多数流行的编程语言都无法区分可空类型和不可空类型。 无法可靠地声明永远不能将null分配给给定的对象引用。 在某些语言中,可以使用注释,例如Java中的非标准注释@Nullable和@NonNullable。 这是一个例子:

interface Person {    public @Nonnull String getName();    public @Nullable Date getDateOfFirstMarriage();}

However, such annotations are not used by the compiler to ensure null-safety. Still, they are useful for the human reader, and they can be used by IDEs and tools such as static code analyzers.

但是,编译器不使用此类注释来确保空安全性。 尽管如此,它们仍然对人类读者有用,并且可以被IDE和静态代码分析器之类的工具使用。

It is important to note that null should not be used to denote error conditions.

重要的是要注意,不应使用null表示错误条件。

Consider a function that reads configuration data from a file. If the file doesn’t exist or is empty, then a default configuration should be returned. Here is the function’s signature:

考虑一个从文件中读取配置数据的函数。 如果文件不存在或为空,则应返回默认配置。 这是函数的签名:

public Config readConfigFromFile ( File file )

What should happen in case of a file read error?

如果出现文件读取错误该怎么办?

Simply return null?

只需返回null

NO!

没有!

Each language has it’s own standard way to signal error conditions and provide data about the error, such as a description, type, stack trace, and so on. Many languages (C#, Java, etc.) use an exception mechanism, and exceptions should be used in these languages to signal run-time errors. readConfigFromFile should not return null to denote an error. Instead, the function's signature should be changed in order to make it clear that the function might fail:

每种语言都有其自己的标准方式来表示错误情况并提供有关错误的数据,例如描述,类型,堆栈跟踪等。 许多语言(C#,Java等)都使用异常机制,并且应在这些语言中使用异常来表示运行时错误。 readConfigFromFile不应返回null来表示错误。 相反,应更改函数的签名,以使其清楚函数可能失败:

public Config readConfigFromFile ( File file ) throws IOException

Remember:

记得:

Allow null only if it makes sense for an object reference to have 'no value associated with it'.

仅当对对象引用有意义时才允许为null

Don’t use null to signal error conditions.

不要使用null来表示错误情况。

零安全 (Null-safety)

Consider the following code:

考虑以下代码:

String name = null;int l = name.length();

At run-time, the above code results in the infamous null pointer error, because we try to execute a method of a reference that points to null. In C#, for example, a NullReferenceException is thrown, in Java it is a NullPointerException.

在运行时,上面的代码导致臭名昭著的null指针错误 ,因为我们尝试执行指向null的引用的方法。 例如,在C#中,抛出NullReferenceException ,在Java中,它是NullPointerException

The null pointer error is nasty.

空指针错误是令人讨厌的。

It is the most frequent bug in many software applications, and has been the cause for countless troubles in the history of software development. Tony Hoare, the inventor of null, calls it the 'billion-dollar mistake'.

它是许多软件应用程序中最常见的错误 ,并且已成为软件开发历史上无数麻烦的原因。 null的发明者Tony Hoare称之为“十亿美元的错误”。

But Tony Hoare (Turing Award winner in 1980 and inventor of the Quicksort algorithm), also gives a hint to a solution in his speech:

但是Tony Hoare(1980年的图灵奖获得者,Quicksort算法的发明者)在演讲中也暗示了一个解决方案:

More recent programming languages … have introduced declarations for non-null references. This is the solution, which I rejected in 1965.
较新的编程语言…引入了非空引用的声明。 这是解决方案,我在1965年拒绝了。

Contrary to some common belief, the culprit is not null per se. The problem is the lack of support for null handling in many programming languages. For example, at the time of writing (May 2018), none of the top ten languages in the Tiobe index natively differentiates between nullable and non-nullable types.

与某些普遍的看法相反,罪魁祸首本身并不是null 。 问题在于许多编程语言中缺少对null处理的支持 。 例如,在撰写本文时(2018年5月), Tiobe索引中的前十种语言都没有原生地区分可空和不可空类型。

Therefore, some new languages provide compile-time null-safety and specific syntax for conveniently handling null in source code. In these languages, the above code would result in a compile-time error. Software quality and reliability increases considerably, because the null pointer error delightfully disappears.

因此,某些新语言提供了编译时的null安全性和特定的语法,以方便地在源代码中处理null 。 在这些语言中,以上代码将导致编译时错误。 软件质量和可靠性大大提高,因为空指针错误令人愉快地消失了。

Null-safety is a fascinating topic that deserves its own article.

空安全是一个引人入胜的话题,值得一读。

Remember:

记得:

Whenever possible, use a language that supports compile-time null-safety.

尽可能使用支持编译时空安全性的语言

Note: Some programming languages (mostly functional programming languages like Haskell) don’t support the concept of null. Instead, they use the Maybe/Optional Pattern to represent the ‘absence of a value’. The compiler ensures that the ‘no value’ case is handled explicitly. Hence, null pointer errors cannot occur.

注意:某些编程语言(大多数是函数式编程语言,例如Haskell)不支持null的概念。 而是使用Maybe / Optional模式 代表“缺乏价值”。 编译器确保明确处理“无值”情况。 因此,不会发生空指针错误。

摘要 (Summary)

Here is a summary of key points to remember:

以下是要记住的关键点的摘要:

  • If a reference points to null, it always means that there is no value associated with it.

    如果引用指向null ,则始终意味着没有与之关联的值

  • In most cases, null has a more specific meaning that depends on the context.

    在大多数情况下, null具有取决于上下文的更具体的含义。

  • If we need to know why there is no value associated with a reference, then additional data must be provided to differentiate the possible cases.

    如果我们需要知道为什么没有与引用相关联的值,则必须提供其他数据来区分可能的情况。

  • Allow null only if it makes sense for an object reference to have 'no value associated with it'.

    仅当对对象引用有意义'没有关联的null才允许为null

  • Don’t use null to signal error conditions.

    不要使用null来表示错误情况。

  • The concept of null exists only for reference types. It doesn't exist for value types.

    null的概念仅适用于引用类型。 对于值类型不存在。

  • In some languages null is the default value for reference types.

    在某些语言中, null是引用类型的默认值。

  • null operations are exceedingly fast and cheap.

    null操作极其快速且廉价。

  • Whenever possible, use a language that supports compile-time-null-safety.

    尽可能使用支持compile-time-null-safety的语言。

翻译自: https://www.freecodecamp.org/news/a-quick-and-thorough-guide-to-null-what-it-is-and-how-you-should-use-it-d170cea62840/

eclipse快速使用指南

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值