java.lang.Long.signum(long i) 是 Java 中用于获取 long 类型数值符号函数(Sign Function) 的静态方法。它返回一个整数值,表示指定 long 值的符号:正数、负数或零。该方法在数学计算、排序逻辑、条件判断和数值分析中非常有用,能够简洁地判断一个数的正负性。

一、方法定义

public static int signum(long i)
  • java.lang.Long
  • 参数long i —— 要检查符号的长整型值
  • 返回值int 类型,含义如下:
    • 1:如果 i > 0
    • 0:如果 i == 0
    • -1:如果 i < 0
  • 异常:无
  • 自版本:JDK 1.5

🔗 类似方法:

  • Integer.signum(int i)
  • Math.signum(double/float)(返回 double

二、功能说明

signum 是数学中的符号函数,定义为:

signum(x) =  1,  if x >  0
            0,  if x == 0
           -1,  if x <  0

Long.signum() 正是这一函数在 long 类型上的实现。它不关心数值大小,只关注其符号。


三、示例代码

public class LongSignumExample {
    public static void main(String[] args) {
        // 正数
        System.out.println(Long.signum(100L));     // 输出: 1
        System.out.println(Long.signum(1L));       // 输出: 1
        System.out.println(Long.signum(Long.MAX_VALUE)); // 输出: 1

        // 零
        System.out.println(Long.signum(0L));       // 输出: 0

        // 负数
        System.out.println(Long.signum(-1L));      // 输出: -1
        System.out.println(Long.signum(-100L));    // 输出: -1
        System.out.println(Long.signum(Long.MIN_VALUE)); // 输出: -1

        // 常见用途:判断正负
        long value = -50L;
        int sign = Long.signum(value);
        if (sign == 1) {
            System.out.println("正数");
        } else if (sign == -1) {
            System.out.println("负数");
        } else {
            System.out.println("零");
        }
        // 输出: 负数
    }
}

四、使用技巧

1. 简化条件判断

// 代替复杂的 if-else 判断
if (Long.signum(x) == Long.signum(y)) {
    System.out.println("x 和 y 同号");
}

2. 排序比较器中的符号提取

Comparator<Long> comparator = (a, b) -> Long.signum(a - b);
// 注意:a - b 可能溢出,更安全写法见下文

3. 数学计算中的符号控制

long magnitude = 100L;
long direction = -1L;
long result = magnitude * Long.signum(direction); // -100

4. 与 Math.signum() 对比使用

double d = -123.45;
int signFromMath = (int) Math.signum(d); // -1
int signFromLong = Long.signum((long) d); // -1

5. 安全的比较器写法(避免溢出)

Comparator<Long> safeComparator = (a, b) -> {
    if (a < b) return -1;
    if (a > b) return 1;
    return 0;
};
// 或使用 Integer.signum(Long.compare(a, b))

五、常见错误

错误 说明
误用 a - b 作为 signum 参数 long 减法可能溢出,导致符号错误
混淆返回类型 返回 int 而非 long
认为 signum 可用于浮点数 应使用 Math.signum(double) 处理浮点数
忽略 Long.MIN_VALUE 特殊性 其绝对值大于 Long.MAX_VALUE,但 signum 正常返回 -1

错误示例(溢出):

long a = Long.MAX_VALUE;
long b = -1L;
// ❌ a - b 溢出为负数,signum 返回 -1,逻辑错误
int wrongSign = Long.signum(a - b); // -1,但 a > b

六、注意事项

  1. 无异常抛出:任何 long 值(包括 MIN_VALUE, MAX_VALUE, 0)都合法。
  2. ⚠️ 减法溢出风险:不要将 a - b 直接传给 signum 来比较大小。
  3. 性能极高:内部实现为简单条件判断,接近常数时间 O(1)
  4. 线程安全:静态无状态方法,可并发调用。
  5. 精度无损失long 是整型,无浮点精度问题。

七、最佳实践

  1. 用于符号判断,而非大小比较

    // ✅ 好:判断符号
    if (Long.signum(value) < 0) { /* 负数 */ }
    
    // ❌ 坏:用于比较(可能溢出)
    // if (Long.signum(a - b) > 0) { /* a > b */ }
    
  2. 安全比较使用 Long.compare(a, b)

    int cmp = Long.compare(a, b); // 返回 -1, 0, 1
    
  3. Math.abs() 结合使用

    long absValue = Math.abs(value);
    int sign = Long.signum(value);
    long original = absValue * sign; // 恢复符号(注意:Long.MIN_VALUE 除外)
    
  4. 在泛型或函数式编程中作为映射函数

    List<Long> numbers = Arrays.asList(10L, -5L, 0L, -1L);
    List<Integer> signs = numbers.stream()
                                 .map(Long::signum)
                                 .toList(); // [1, -1, 0, -1]
    

八、性能优化

  1. 极高效,无需优化

    • signum 内部是几个条件判断,性能已最优。
  2. 避免重复调用

    // ❌
    if (Long.signum(x) == 1) { ... }
    process(Long.signum(x));
    
    // ✅
    int sign = Long.signum(x);
    if (sign == 1) { ... }
    process(sign);
    
  3. 在热点代码中可内联(JVM 自动优化)

    • 无需手动展开。

九、总结

特性 说明
方法 Long.signum(long i)
返回值 1(正)、0(零)、-1(负)
用途 判断 long 值的符号
性能 极高,O(1),无对象创建
安全性 无异常,支持所有 long

核心要点:

  1. 只关心符号,不关心大小
  2. 返回值为 int,但语义清晰
  3. ⚠️ 禁止用 a - b 计算差值符号(溢出风险)。
  4. 🔄 Long.compare(a, b) 配合使用更安全
  5. 🚀 性能卓越,适合高频调用场景