前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么 NULL 是你代码中的无声杀手?

为什么 NULL 是你代码中的无声杀手?

作者头像
DevOps云学堂
发布2024-06-11 17:23:38
800
发布2024-06-11 17:23:38
举报
文章被收录于专栏:DevOps持续集成DevOps持续集成

在软件开发领域,很少有问题像NULL值一样普遍存在且危害巨大。这个看似无害的占位符可能会给代码库带来重大问题,造成难以发现的漏洞,并损害数据完整性。尽管 NULL 有其用途,但处理不当且不了解其含义可能会导致严重问题。我们将在这篇详尽的博客文章中探讨 NULL 被称为代码中的无声杀手的原因,提供代码示例来展示其后果,并讨论减轻其负面影响的方法。

1. 简介

NULL 是一个看似简单的概念,表示没有值。尽管 NULL 很简单,但它却因在软件应用程序中引起大量问题而臭名昭著。Tony Hoare 于 1965 年引入了 NULL 引用的概念,他经常将其称为“十亿美元的错误”。这篇文章旨在探讨 NULL 为何如此成问题,并为开发人员提供有效处理它的实用解决方案。

2. NULL 的概念

NULL 是编程中用于表示变量没有值的特殊标记。它不同于零、空字符串或任何其他“假”值。NULL 的存在可能表示未初始化的变量、缺失的数据或可选字段。

NULL 的问题

NULL 的根本问题是它的歧义性。它可能意味着:

  • 值未知。
  • 值不存在。
  • 值不适用。

这种模糊性可能会导致混乱和错误,尤其是在没有充分检查或处理 NULL 值时。

3. NULL 导致的常见问题

空指针异常

与 NULL 相关的最臭名昭著的问题之一是 NULL 指针异常 (NPE)。当程序尝试使用预期为对象但实际上为 NULL 的引用时,就会发生这种情况。在许多编程语言中,取消引用 NULL 指针会导致运行时错误,从而导致程序崩溃。

Java 示例:
代码语言:javascript
复制
public class NullPointerExample {
    public static void main(String[] args) {
        String str = null;
        try {
            System.out.println(str.length());
        } catch (NullPointerException e) {
            System.out.println("Caught a NullPointerException");
        }
    }
}

数据不一致

数据库中的 NULL 值可能会导致查询出现不一致和意外结果。例如,涉及 NULL 值的聚合和连接可能无法按预期运行。

SQL 示例:
代码语言:javascript
复制
SELECT AVG(salary) FROM employees WHERE department_id = 10;

从员工中选择AVG (薪水) ,其中部门 ID = 10 ;如果某些工资值为空,则平均值计算可能会排除这些条目,从而导致结果偏差。

额外绩效开销

处理 NULL 值通常需要在代码中进行额外的检查和分支,这会带来性能开销。这在性能至关重要的应用程序中尤其成问题,因为每微秒都至关重要。

4. 真实世界的代码示例

Java 中的 NULL

Java 开发人员经常遇到与 NULL 相关的问题,主要是 NULL 指针异常。Java 的类型系统允许将 NULL 分配给任何对象引用,这很容易引入错误。

例子:
代码语言:javascript
复制
public class Employee {
    private String name;
    private Integer age;
    public Employee(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public Integer getAge() {
        return age;
    }
}
public class NullExample {
    public static void main(String[] args) {
        Employee emp = new Employee(null, null);
        try {
            System.out.println(emp.getName().toUpperCase());
        } catch (NullPointerException e) {
            System.out.println("Caught a NullPointerException");
        }
    }
}

Python 中的 NULL

Python 使用关键字处理 NULL 值None。虽然 Python 是动态类型的,这降低了一些风险,但如果处理不当,NULL 值仍然会导致运行时错误。

例子:
代码语言:javascript
复制
def print_length(s):
    try:
        print(len(s))
    except TypeError:
        print("Caught a TypeError because the input was None")
print_length(None)

SQL 中的 NULL

SQL 数据库使用 NULL 来表示缺失或未知值。但是,涉及 NULL 的运算可能会产生意外结果,尤其是在相等和聚合方面。

例子:
代码语言:javascript
复制
SELECT * FROM employees WHERE manager_id = NULL; --不会返回任何 rows
SELECT * FROM employees WHERE manager_id IS NULL; -- 检查NULL的正确方法

5. 处理 NULL 的策略

使用可选类型

许多现代语言都提供可选或可空类型,以明确处理值的存在或不存在。这种方法鼓励开发人员考虑 NULL 的可能性并进行适当处理。

Java 示例(使用Optional):
代码语言:javascript
复制
import java.util.Optional;
public class Employee {
    private Optional<String> name;
    private Optional<Integer> age;
    public Employee(Optional<String> name, Optional<Integer> age) {
        this.name = name;
        this.age = age;
    }
    public Optional<String> getName() {
        return name;
    }
    public Optional<Integer> getAge() {
        return age;
    }
}
public class OptionalExample {
    public static void main(String[] args) {
        Employee emp = new Employee(Optional.of("John Doe"), Optional.empty());
        emp.getName().ifPresent(name -> System.out.println(name.toUpperCase()));
        emp.getAge().ifPresentOrElse(
            age -> System.out.println("Age: " + age),
            () -> System.out.println("Age not available")
        );
    }
}

默认值和保护

设置默认值并使用保护可以帮助避免与 NULL 相关的问题。这在配置和可选字段中特别有用。

Python 中的示例:
代码语言:javascript
复制
def get_employee_name(employee):
    return employee.get('name', 'Unknown')
employee = {}
print(get_employee_name(employee))  # Outputs 'Unknown'

NULL 对象模式

NULL 对象模式涉及创建一个表示默认行为的对象,而不是使用 NULL。这可以帮助避免 NULL 检查并使代码更具可读性。

Java 示例:
代码语言:javascript
复制
public interface Employee {
    String getName();
}
public class RealEmployee implements Employee {
    private String name;
    public RealEmployee(String name) {
        this.name = name;
    }
    @Override
    public String getName() {
        return name;
    }
}
public class NullEmployee implements Employee {
    @Override
    public String getName() {
        return "No Name Available";
    }
}
public class NullObjectPatternExample {
    public static void main(String[] args) {
        Employee emp = getEmployee(false);
        System.out.println(emp.getName());
    }
    public static Employee getEmployee(boolean isReal) {
        if (isReal) {
            return new RealEmployee("John Doe");
        } else {
            return new NullEmployee();
        }
    }
}

数据库约束和默认值

使用数据库约束和默认值可以防止将 NULL 插入不适当的字段。这确保了数据库级别的数据完整性。

SQL 示例:
代码语言:javascript
复制
CREATE TABLE employees (
  id INT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  salary DECIMAL(10, 2) DEFAULT 0.00
);
INSERT INTO employees (id, name) VALUES (1, 'John Doe'); -- salary will default to 0.00

6.结论

NULL 通常是代码中的隐形杀手,会导致微妙的错误、崩溃和数据不一致。通过了解它可能引起的问题并实施强大的策略来处理它,开发人员可以显著提高其应用程序的可靠性和可维护性。无论是通过使用可选类型、设置默认值、采用 NULL 对象模式还是强制执行数据库约束,都有许多方法可以减轻与 NULL 相关的风险。 采用这些最佳实践不仅有助于编写更安全、更可预测的代码,还可以提高软件系统的整体质量。请记住,解决问题的第一步是识别问题,对于任何旨在构建弹性和健壮应用程序的开发人员来说,承认 NULL 的潜在陷阱都至关重要。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DevOps云学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 简介
  • 2. NULL 的概念
    • NULL 的问题
    • 3. NULL 导致的常见问题
      • 空指针异常
        • Java 示例:
      • 数据不一致
        • SQL 示例:
      • 额外绩效开销
      • 4. 真实世界的代码示例
        • Java 中的 NULL
          • 例子:
        • Python 中的 NULL
          • 例子:
        • SQL 中的 NULL
          • 例子:
      • 5. 处理 NULL 的策略
        • 使用可选类型
          • Java 示例(使用Optional):
        • 默认值和保护
          • Python 中的示例:
        • NULL 对象模式
          • Java 示例:
        • 数据库约束和默认值
          • SQL 示例:
      • 6.结论
      相关产品与服务
      数据库
      云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档