Java中Long与long的转换及空值处理

0 次阅读

Java语言中,Long与long是开发过程中经常接触的一组数据类型。虽然二者都用于表示整数类型,但它们在数据结构、内存占用、默认值以及空值处理方面存在明显区别。尤其是在数据库操作、接口参数传递、实体类设计等场景中,如果没有正确处理Long和long之间的转换,很容易出现空指针异常等问题。

理解Long与long的区别,并掌握安全转换方式,是Java开发中避免隐藏Bug的重要基础。

Long与long的基本区别

long是Java中的基本数据类型(Primitive Type),而Long是Java提供的包装类型(Wrapper Class),属于对象类型。

二者最大的区别如下:

对比项longLong
类型基本数据类型包装类
默认值0null
是否可以为空不支持支持
是否属于对象
是否可以调用方法可以
泛型支持不支持支持

例如:

Java
long number = 100L;

Long objectNumber = 100L;

long直接存储数值,而Long实际上是一个对象引用,内部封装了一个long类型的数据。

在实际开发中,如果字段可能不存在或者数据库字段允许为空,通常建议使用Long,而不是long。

例如:

Java
public class User {

    private Long id;

    private String username;

}

如果数据库中的id没有赋值,Long可以表示为null:

Java
user.setId(null);

而使用long:

Java
private long id;

即使没有初始化,也会自动赋值为0,无法区分“没有值”和“真实值为0”。


Long转换为long的方法

Long转换为long属于对象类型向基本类型转换,也称为拆箱(Unboxing)。

自动拆箱

Java支持自动拆箱,可以直接赋值:

Java
Long value = 100L;

long result = value;

编译器会自动转换为:

Java
long result = value.longValue();

这种方式代码简单,但存在一个隐藏风险。

如果Long对象为null:

Java
Long value = null;

long result = value;

运行时会抛出:

java.lang.NullPointerException

原因是Java尝试调用:

Java
value.longValue();

而null对象无法调用方法。


使用longValue()显式转换

Long提供了longValue()方法:

Java
Long value = 200L;

long result = value.longValue();

这种写法更加明确,但仍然不能处理null:

Java
Long value = null;

long result = value.longValue();

依然会出现空指针异常。

因此,在实际项目中不建议直接调用longValue()处理未知来源的数据。


long转换为Long的方法

long转换为Long属于自动装箱(Boxing)。

自动装箱

Java可以自动完成转换:

Java
long number = 300L;

Long result = number;

等价于:

Java
Long result = Long.valueOf(number);

自动装箱通常不会产生问题,因为long一定存在值。


使用Long.valueOf()

推荐显式转换:

Java
long number = 500L;

Long result = Long.valueOf(number);

相比直接new Long:

Java
Long result = new Long(number);

valueOf()更加推荐,因为Java可以对部分Long对象进行缓存优化。


Long转long时的空值处理

Long最大的风险就是null转换问题。

例如:

Java
public long getUserId(Long id) {
    return id;
}

如果调用:

Java
getUserId(null);

程序会直接抛出NullPointerException。

因此,需要进行空值判断。


方法一:使用if判断

最基础的处理方式:

Java
public long convert(Long value) {

    if (value != null) {
        return value;
    }

    return 0L;
}

调用:

Java
Long number = null;

long result = convert(number);

结果:

0

这种方式逻辑清晰,适合业务规则明确的场景。


方法二:使用三元表达式

代码更加简洁:

Java
Long value = null;

long result = value != null ? value : 0L;

如果value存在,则返回实际值,否则返回默认值。

常用于实体对象转换:

Java
long count = user.getCount() != null ? user.getCount() : 0L;

方法三:使用Optional处理null

Java 8之后,可以使用Optional:

Java
Long value = null;

long result = Optional.ofNullable(value)
        .orElse(0L);

如果Long为空,则返回0。

在复杂对象链式调用中,Optional可提高代码安全性:

Java
long id = Optional.ofNullable(user)
        .map(User::getId)
        .orElse(0L);

可以避免多层null判断。


方法四:使用Apache Commons工具类

Apache Commons Lang提供了NumberUtils工具:

Java
long result = NumberUtils.toLong(null);

返回:

0

也可以指定默认值:

Java
long result = NumberUtils.toLong(null, -1L);

返回:

-1

在大型项目中,这类工具方法可以减少重复代码。


数据库场景中的Long与long选择

数据库开发中,Long和long的选择非常重要。

例如:

Java
@Entity
public class Order {

    private Long id;

    private Long userId;

}

通常推荐使用Long。

原因包括:

1. 数据库字段可能为空

数据库查询结果可能不存在:

SQL
select user_id from order_table;

如果字段允许NULL:

NULL

无法映射到long。


2. ORM框架需要区分状态

例如MyBatis、Hibernate等框架中:

Java
Long id;

可以表示:

  • 未赋值

  • 已赋值

  • 数据不存在

而:

Java
long id;

只能表示:

  • 0

  • 非0数字

无法表达空状态。


3. 主键字段推荐Long

实际项目中常见:

Java
private Long id;

原因是数据库自增ID通常需要区分:

  • 新对象

  • 已保存对象

例如:

Java
User user = new User();

user.getId();

如果id为null,说明对象尚未入库。


Long比较时的注意事项

Long属于对象类型,不能简单使用==比较。

错误方式:

Java
Long a = 100L;
Long b = 100L;

System.out.println(a == b);

虽然部分情况下结果可能为true,但这是因为Long缓存机制导致的。

推荐使用:

Java
a.equals(b);

例如:

Java
Long a = 1000L;
Long b = 1000L;

System.out.println(a.equals(b));

结果:

true

如果考虑null情况:

Java
Objects.equals(a, b);

更加安全:

Java
boolean result = Objects.equals(a, b);

当其中一个值为null时,也不会出现异常。


Long与long转换中的常见错误

错误一:直接拆箱导致空指针

代码:

Java
Long count = null;

long total = count;

问题:

NullPointerException

解决:

Java
long total = count == null ? 0L : count;

错误二:实体类全部使用long

例如:

Java
class Product {

    private long price;

}

问题:

数据库NULL无法映射。

建议:

Java
private Long price;

错误三:使用==比较Long

错误:

Java
Long a = 1000L;
Long b = 1000L;

if(a == b){
}

应该:

Java
if(Objects.equals(a,b)){
}

Java项目中的最佳实践

在实际开发中,可以遵循以下原则:

1. 数据库字段优先使用Long

特别是:

  • 主键ID

  • 外键ID

  • 可为空字段

  • 接口返回字段

例如:

Java
private Long userId;

2. 方法参数根据业务决定

如果参数必须存在:

Java
public void update(long id)

如果参数允许为空:

Java
public void update(Long id)

3. 转换时始终考虑null

不要:

Java
long value = object.getValue();

推荐:

Java
long value = Objects.requireNonNullElse(
        object.getValue(),
        0L
);

Java 9以后可以使用这种方式。


4. 使用包装类处理业务数据

业务层推荐:

Java
Long amount;

计算阶段转换:

Java
long total = amount == null ? 0L : amount;

这样可以兼顾数据表达能力和计算效率。


总结

Java中的Long与long虽然都表示长整型数据,但二者在使用场景上存在明显差异。long属于基本类型,性能更高,但无法表示空值;Long属于对象类型,可以表示null,更适合用于实体类、数据库字段以及接口数据传输。

进行Long和long转换时,最需要关注的是自动拆箱带来的空指针问题。开发过程中,应避免直接将可能为null的Long赋值给long变量,而应通过条件判断、Optional、Objects.requireNonNullElse等方式进行安全处理。

合理选择Long和long,并建立规范的空值处理习惯,可以有效提升Java程序的稳定性和可维护性。