杰瑞科技汇

Java byte 转 long 有哪些方法?

在 Java 中,将 byte 类型转换为 long 类型是一个相对简单的过程,因为 long 是一个更大的数据类型,可以无损地容纳 byte 的所有可能值,Java 会自动进行这种转换,称为 widening primitive conversion (拓宽原始类型转换)

Java byte 转 long 有哪些方法?-图1
(图片来源网络,侵删)

下面我将从简单到复杂,详细解释各种场景下的转换方法。

基本转换(无符号问题)

这是最常见的情况,你只需要将一个 byte 值提升为 long,Java 会自动处理这个转换。

方法:直接赋值

public class ByteToLongExample {
    public static void main(String[] args) {
        byte myByte = 100;
        long myLong = myByte; // 自动类型转换
        System.out.println("原始 byte 值: " + myByte);
        System.out.println("转换后的 long 值: " + myLong);
        System.out.println("myLong 的类型: " + ((Object)myLong).getClass().getSimpleName());
    }
}

输出:

Java byte 转 long 有哪些方法?-图2
(图片来源网络,侵删)
原始 byte 值: 100
转换后的 long 值: 100
myLong 的类型: Long

解释: 由于 long 的范围(-2⁶³ 到 2⁶³-1)远大于 byte 的范围(-128 到 127),所以这个转换是安全的,不会丢失任何信息。


处理负数(有符号扩展)

byte 是一个有符号的 8 位整数,当 byte 的值为负数时(-1),直接转换为 long 会保留其符号。

方法:直接赋值

public class NegativeByteToLong {
    public static void main(String[] args) {
        byte negativeByte = -1;
        long myLong = negativeByte;
        System.out.println("原始 byte 值: " + negativeByte);
        System.out.println("转换后的 long 值: " + myLong);
        System.out.println("long 的二进制表示: " + Long.toBinaryString(myLong));
    }
}

输出:

原始 byte 值: -1
转换后的 long 值: -1
long 的二进制表示: 1111111111111111111111111111111111111111111111111111111111111111

解释: 在 Java 中,byte, short, charint, long 的转换会进行符号扩展,这意味着如果原始值的最高位是 1(表示负数),那么在转换到更大的类型时,所有新增的高位都会被填充为 1。byte-1(二进制 11111111)转换为 long 后,会变成 64 个 1,这仍然是 -1long 表示。


byte 视为无符号数(常见陷阱)

这是一个非常关键且常见的场景,在某些情况下,你希望将 byte 的 8 位解释为一个无符号的 0 到 255 之间的数,而不是 -128 到 127 之间的有符号数。

  • byte b = -1; 如果你把它当作无符号数,它实际代表的是 255 (2⁸ - 1)。
  • byte b = 127; 有符号和无符号值相同。
  • byte b = -128; 如果你把它当作无符号数,它实际代表的是 128

方法:使用 & 0xFF

这是在 Java 中将 byte 转换为无符号 long 的标准方法,其原理是利用位运算来消除符号扩展的影响。

public class UnsignedByteToLong {
    public static void main(String[] args) {
        byte signedByte = -1;
        // 1. Java 会将 byte -1 自动扩展为 int -1 (符号扩展)
        //    int value = -1; (二进制: 1111...1111)
        // 2. 进行与 0xFF (二进制: 0000...00000000000000000011111111) 的位与运算
        //    1111...1111
        // & 0000...00000000000000000011111111
        // -------------------------------
        //    0000...00000000000000000011111111  结果是 255
        long unsignedLong = signedByte & 0xFFL;
        System.out.println("原始有符号 byte 值: " + signedByte);
        System.out.println("视为无符号数后的 long 值: " + unsignedLong);
    }
}

输出:

原始有符号 byte 值: -1
视为无符号数后的 long 值: 255

为什么是 0xFFL 而不是 0xFF

  • 0xFF 是一个 int 类型的常量。
  • 当你执行 byte & int 时,byte 会被先提升为 int(发生符号扩展),然后进行运算。
  • 使用 0xFFLlong 类型)可以确保整个运算在 long 类型域中进行,虽然在这个特定例子中结果是一样的,但这是一个更健壮、更清晰的写法,可以避免潜在的混淆。

从字节数组(byte[])转换

在网络编程、文件处理等场景中,你经常需要从一个字节数组中读取多个字节来组合成一个 long,这里的关键是考虑字节序

a) 大端序

最高有效字节在最前面。

public class BytesToLongBigEndian {
    public static long bytesToLongBE(byte[] bytes) {
        long value = 0;
        // 从第一个字节(最高位)开始处理
        for (int i = 0; i < bytes.length; i++) {
            // 将每个字节左移到正确的位置,然后进行或运算
            value |= ((long) bytes[i] & 0xFF) << (8 * (bytes.length - 1 - i));
        }
        return value;
    }
    public static void main(String[] args) {
        // 假设我们想表示 long 值 0x123456789ABCDEF0 (大端序)
        byte[] bytes = {
            (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78,
            (byte) 0x9A, (byte) 0xBC, (byte) 0xDE, (byte) 0xF0
        };
        long result = bytesToLongBE(bytes);
        System.out.println("从字节数组(大端序)转换得到的 long 值: 0x" + Long.toHexString(result));
    }
}

b) 小端序

最低有效字节在最前面。

public class BytesToLongLittleEndian {
    public static long bytesToLongLE(byte[] bytes) {
        long value = 0;
        // 从最后一个字节(最低位)开始处理
        for (int i = 0; i < bytes.length; i++) {
            // 将每个字节左移到正确的位置,然后进行或运算
            value |= ((long) bytes[i] & 0xFF) << (8 * i);
        }
        return value;
    }
    public static void main(String[] args) {
        // 同样的 long 值 0x123456789ABCDEF0,在小端序的字节数组中是这样存放的
        byte[] bytes = {
            (byte) 0xF0, (byte) 0xDE, (byte) 0xBC, (byte) 0x9A,
            (byte) 0x78, (byte) 0x56, (byte) 0x34, (byte) 0x12
        };
        long result = bytesToLongLE(bytes);
        System.out.println("从字节数组(小端序)转换得到的 long 值: 0x" + Long.toHexString(result));
    }
}
场景 方法 关键点
基本转换 long l = b; Java 自动进行有符号的拓宽转换。
处理负数 long l = b; 会进行符号扩展,结果仍然是一个负数。
视为无符号数 long l = b & 0xFFL; 使用 & 0xFF 消除符号位,将值映射到 0-255。
字节数组转 long ((long) b & 0xFF) << (8 * i) 必须指定字节序(大端/小端),并对每个字节进行无符号处理。

选择哪种方法完全取决于你的业务需求,如果你只是在数值计算中传递 byte 值,直接赋值即可,如果你在处理二进制数据(如网络协议、文件格式),并且需要将 byte 解释为 0-255 的值,& 0xFF 是必不可少的。

分享:
扫描分享到社交APP
上一篇
下一篇