【问题标题】:What does is mean by null pointing to nothing and why use null at all?null 指向空是什么意思,为什么要使用 null?
【发布时间】:2013-11-10 21:44:18
【问题描述】:

有很多关于 null 和 in java 的问题。

我无法理解的是人们所说的 null 的意思是什么都不指向或为什么要使用 null。

我无法理解两者之间的区别

String thing = null;

String thing = "";

这个问题有详细的答案What is null in Java?,但我就是想不通。

我错过了什么?


我学过的语言(非专家)

Python, vb (vb.net), 网页编程(html, css, php, bit of js), sql

我应该补充一下,正是这个答案https://stackoverflow.com/a/19697058/2776866促使我写了这个。

【问题讨论】:

  • 您还知道哪些其他编程语言?所以我们有一个参考点?
  • 从您列出的语言来看,它有点接近 VB 中的 nothing 而不太接近 SQL 中的 NULL
  • 如果你懂C,这个问题就很简单了。
  • @Skippy:我的意思是,如果你想成为一名认真的程序员,你应该学习C。很多问题都会变得微不足道。

标签: java pointers null


【解决方案1】:
String str = null;

表示一个String引用,命名为str,不指向任何东西

String str = "";

表示一个名为 str 的 String 引用,指向一个实际的 String 实例。对于那个 String 实例,它是一个长度为零的 String,但它仍然是一个实际的对象。


稍微更新一些图表,希望可以帮助您形象化:

假设我有

String nullStr = null;
String emptyStr = "";
String myStr = "ab";

它在概念上的样子:

  // String nullStr = null;

  nullStr ----------> X    pointing to nothing



  // String emptyStr = "";
                      +------------------+
  emptyStr ---------> |       String     |
                      +------------------+
                      | length = 0       |
                      | content = []     |
                      +------------------+


  // String myStr = "ab";
                      +------------------+
  myStr ------------> |       String     |
                      +------------------+
                      | length = 2       |
                      | content = [ab]   |
                      +------------------+

(当然String对象的内部结构并不是Java中的实物,只是给大家一个思路)


更多关于 NULL 背后原理的编辑:

事实上,在某些语言中,它们不提供 NULL 的概念。无论如何,在 Java(或类似语言)中,Null 意味着与“空”对象语义不同。以 String 为例,我可能有一个 People 类,它带有 String preferedTitle 属性。 Null preferedTitle 表示该人有 NO 首选头衔(因此我们可能需要派生并显示它的头衔),而 preferedTitle是一个空字符串意味着 IS 有一个首选标题,并且没有显示任何内容。

顺便说一句,虽然有点离题:Null 的概念对某些人来说被视为有问题(因为它需要所有额外的处理等)。因此,一些语言(例如 Haskell)正在使用其他一些方法来处理我们过去使用 Null 的情况。

【讨论】:

  • 让我画一点 ascii 艺术,希望它能帮助你想象一下,就这样
  • @Skippy:这是个好问题。事实上,在某些语言中,它们不提供 NULL 的概念。无论如何,在 Java(或类似语言)中,Null 意味着在语义上与“空”对象不同。以 String 为例,我可能有一个带有 String preferedTitle 属性的 People 类。 Null preferedTitle 表示该人没有首选头衔(因此我们可能需要派生并显示它的头衔),而 preferedTitle 为空字符串意味着存在首选头衔,这正在显示什么都没有。
  • 顺便说一句,Null 的概念对某些人来说被视为有问题(因为它需要所有额外的处理等)。因此,一些语言(例如 Haskell?)正在使用其他方式来处理我们过去使用 Null 的情况。
【解决方案2】:

String str 是一个对象的引用。也就是说,它不是一个实际的对象,而是一个可以包含对象地址的变量。当您为 str 赋值时,您正在更改存储在其中的地址并更改它所寻址的对象。

null 是不指向对象的引用值。这几乎是你所能得到的。如果您将 null 分配给一个字符串引用 (String str = null;),那么您将无法使用该引用调用任何 String 方法——所有尝试都将导致 NullPointerException。

"" 是一个不包含字符的字符串——零长度。不过,它仍然是一个对象,如果您将其地址分配给您的字符串引用变量 (String str = "";),您可以获取其长度,将其与另一个字符串进行比较,提取其 hashCode 等。

【讨论】:

  • 有时你想表明什么都没有。或者,您可以将引用 X 初始化为 null,然后执行一个复杂的算法,该算法应该为 X 分配一个有效值。如果该有效值从未被分配,您可以检测到,因为 X 将为空。
【解决方案3】:

Java 并不真正公开指针,而是处理引用。

当你说

String thing = null;

您是说有一个引用(字符串类型)称为事物,它没有引用任何东西。

当你说

String thing = ""

这是的简写,

String thing = new String("");

现在您已经初始化并准备好使用一个实际的对象。您告诉编译器创建一个字符串,现在您的“事物”引用了新字符串。

如果你想知道你初始化字符串的长度,可以去;

thing.length

这是零。字符串存在,但长度为零。

在 null 版本上尝试 string.length 会导致 NullReferenceException,这是编译器说的

“我试图找出你的字符串的长度,但我找不到!”

【讨论】:

  • 您能否在您的答案中修正String 类的大写。此外,String x = "**"; 和 String x = new String("**"); 不是完全相同的东西,因为它们可以产生不同的内存分配。
  • @PM77-1 没问题,我在 .NET 世界里待得太久了,它不关心字符串与字符串。您对分配的权利,但我更担心的是外行术语,而不是技术上的正确性。
  • @Skippy - 它们都是很好的答案(包括这个)。您只需要了解对象本身和对该对象的引用之间的区别。 null 通常用于表示对象尚未创建或不再需要并且应该可用于垃圾回收。
  • 我对此投了反对票。 “......你是说有一个对象......它没有引用任何东西......” - 不正确。你是说根本没有对象。
  • @Skippy,我认为这里的两个最佳答案是由 Adrian Shum 和 Hot Licks 发布的。他们之间没有什么可以选择的。我猜阿德里安的图表给了他优势。但重要的是你觉得有帮助 - 你问的问题,而不是我。
【解决方案4】:

实际上,null 的意思是“不可用于调用方法”。如果一个对象被允许是null,你必须在调用它的方法之前总是检查它的null

尝试在null 对象上调用任何方法都是无条件的错误。在几乎所有情况下,这也是一个编程错误,因为您应该这样做

  • 确保变量始终为非空,或
  • 在对其调用方法之前检查一个可能合法为 null 的变量。

另一方面,空对象允许您调用方法。例如,您可以找到一个空字符串的长度 - 它为零。您还可以迭代一个字符串,将其传递给需要非空字符串的方法,等等。

要对此进行可视化,请考虑使用Boolean 对象而不是String。与只有两种状态的原始boolean 不同,即true(“是”)和false(“否”),Boolean 对象具有三种状态:

  • 是的
  • 没有
  • 不知道

这第三个“不知道”状态对应于null。它既不是true 也不是false 状态。您的程序可以充分利用这第三种状态 - 例如,您可以使用与 null 的比较来查看是否已设置值,或将值设置为 null 以“取消设置”其值。

【讨论】:

  • "null 表示"不可用于调用方法"" - 并非如此。仍然可以使用强制转换的空引用调用 STATIC 方法。或者你故意不提这个是为了不让它变得更复杂?
  • @Skippy 别担心,掌握基础知识后会更容易。使用 SO 和 Joshua Bloch 的一些书。
  • @TT_ 是的,我不想在其中引入静态方法,以免使事情复杂化。
【解决方案5】:

在 Java 中,null 和空字符串是两个不同的东西。

如果 String 为 null,则无法访问其方法,因为它会抛出 NullPointerException,但如果 String 为 "",则 String 对象有效,您可以访问其方法。

例如

 String a = null;
 String b = "";

 System.out.println (a.length());   // No Good
 System.out.println (b.length());   // Prints 0

【讨论】:

    【解决方案6】:

    让我们将其与 Python 进行比较。在 Python 中,null 等价于 None

    >>> test = ""
    >>> test1 = None
    

    这是设置一个空字符串和一个“null”字符串。

    >>> test
    ''
    >>> test1
    None
    

    在 Python 中,我们可以使用 is 测试无效性

    >>> test is None
    False
    >>> test1 is None
    True
    

    我们可以使用==测试空字符串

    >>> test == ""
    True
    >>> test1 == ""
    False
    

    null(如None)是缺少值。

    【讨论】:

      【解决方案7】:

      从概念上讲,null 是一个特殊值,这意味着该变量指向一个无效对象,因此它不指代任何有效的东西,因为您无法访问其内容(变量或方法)。

      您可以将其视为一种已添加到语言中的特殊条件,因为能够拥有不引用任何内容的指针很有用。但这里有一些不一致之处,事实上,有些语言通过强制你只具有初始化(有意义的)值来阻止null 值的必要性。

      您的示例有所不同,"" 是一个有效对象:它是一个空字符串,而 null 不是一个有效对象。

      【讨论】:

      • @DavidWallace:就是这样。变量没有引用一个有效的对象,或者引用一个无效的对象,你可以看到它两种方式。 “不指代任何东西”的概念只是您赋予null 值本身的含义,它并不意味着绝对任何东西,因为它指的是某物,即null 值本身。那就是null 只是一个值,它代表一个未初始化或未定义的对象,它本质上是无效的。
      • 没有。空变量不引用无效对象。它不引用未初始化的对象。它不引用未定义的对象。空变量根本不引用任何对象,有效或无效,已初始化或未初始化,已定义或未定义。通过引用“指向”某物的对象,您的答案将变量的概念与对象的概念混淆了;这些正是 OP 最需要弄清楚的概念,才能理解这些东西。
      • @DavidWallace:“指针指向无效对象”确实是我修正的错字。但是您的 CAPS 部分是错误的:设置为 null 的变量指的是特定值 null。这是我在回答中试图指出的null 值的常见问题。 null 是一个特殊类型的值,它不是一个对象 (null instanceof Object == false) 但同时它是(将null 分配给任何对象变量都是有效的)。它令人困惑,因为它是,无知比混乱更糟糕。 JSL 明确指出了这种混淆:
      • @DavidWallace:来自 JSL 4.1:还有一种特殊的 null 类型,即表达式 null 的类型,它没有名称。因为 null 类型没有名字,所以不可能声明一个 null 类型的变量或强制转换为 null 类型。空引用是空类型表达式的唯一可能值。空引用始终可以进行扩展引用转换为任何引用类型。
      【解决方案8】:

      尽管许多面向对象的框架使用指针实现引用,但最好不要将引用视为“指向”对象,而是将其视为“标识”它们[个人而言,我喜欢这个词“对象标识符”来描述引用,因为术语“引用”在不同的上下文中有些重载]。尽管对象标识符不是人类可读的,但可以将系统想象为给每个对象一个从 1 开始的关联编号,并且每个类类型变量都具有对象编号或写在其上的零。由于类类型变量和数组槽默认保持为零,并且永远不会有第零个对象,因此未初始化变量或数组槽的默认值变量不会识别有效对象。

      【讨论】:

        【解决方案9】:

        我更喜欢使用容器/盒子的概念来理解这个概念

        让我们从这个开始

        String thing = "";
        

        假设你有一个容器/盒子,只要你把值放在双引号“”之间,你就可以存储任何值,如果你决定只在盒子里放一个没有值的双引号,那绝对没有错了,任何时候你打开你的盒子,你仍然会看到里面的东西(双引号)

        现在这里的大个子叫null

        String thing = null;
        

        简单来说,将 null 视为绝对没有

        这一切意味着什么? 当您打开第一个框时,您会看到双引号 ""

        当您打开第二个盒子时,您什么也看不到(它只是一个空盒子)

        【讨论】:

          猜你喜欢
          • 2014-01-19
          • 1970-01-01
          • 2013-05-09
          • 2012-09-17
          • 2013-08-05
          • 1970-01-01
          • 2017-05-25
          • 1970-01-01
          • 2018-03-19
          相关资源
          最近更新 更多