学习Java遇到的趣事:混乱的一字节

橘子 发布于 2025-05-14 208 次阅读


本科期间压根没有系统性的学习过Java,但是系统性的学习过C/C++。我觉得是挺正确的,这样大一小朋友对于基本数据类型、数据和代码在计算机中的基本样貌之类的知识理解的会更加透彻一些。

我一直都以为,只要学好了C/C++,转其他语言不是什么难事,但是没想到的是,这个想法大致上没问题——知道数据结构、算法之类的,想学Java什么的会有什么困难呢?但是在细节上却有一些问题,就比如说,数据类型。

char 应该是学习C/C++最先接触到的数据类型了吧——毕竟要print hello world嘛。但是就是这个char,却在转向java上出现了很大问题。

C++中的一字节!

C++的char

char 在C++中是只占用一个字节的有符号数字,利用它的0到127的正数表示范围可以表示全部的ASCII码。所以要使用无符号一字节来表示0~255,则应该使用unsigned char

C++的byte

C++中的byte类型比较混乱,由于这玩意似乎并不是系统保留的关键字,所以它可能有很多语义。参考这篇菜鸟教程(下图),就可以发现其中并没有byte。

所以我找到了两种说法:

说法一:std::byte 是C++17 引入的一种独立类型,用于表示内存中的字节。与 char 或 unsigned char 不同,std::byte 不是字符类型,也不是算术类型。它只是位的集合,并且只支持位操作符。参考于这篇CSDN文章。其中对于byte的初始化都是这么干的:

#include <cstddef> // for std::byte
 
std::byte b1{0x3F};
std::byte b2{0b1111'0000};
std::byte b4[4] {b1, b2, std::byte{1}}; // 4 bytes (last is 0)
 
if (b1 == b4[0]) 
{
    b1 <<= 1;
}
 
std::cout << std::to_integer<int>(b1) << '\n'; // outputs: \T{126}

说法二:byte这玩意就是unsigned char。这是我自己试出来的。只需要在头文件中引入 <windows.h>这个头文件,就能使用byte这个数据类型。代码如下:

#include<iostream>
#include <windows.h>

using namespace std;

int main(int argc, char* args[]){
    bool boolTemp = false;
    
    char c1 = 100;
    char c2 = -100;
    printf("c1 value(int)=%d, hex code=%X\n", c1, c1);
    printf("c2 value(int)=%d, hex code=%X\n", c2, c2);
    boolTemp = (c1 > 0) && (c2 < 0);
    printf("(c1 > 0) && (c2 < 0) = %d\n", boolTemp);

    byte b1 = 100;
    byte b2 = -100;
    printf("b1 value(int)=%d, hex code=%X\n", b1, b1);
    printf("b2 value(int)=%d, hex code=%X\n", b2, b2);
    boolTemp = (b1 > 0) && (b2 < 0);
    printf("(b1 > 0) && (b2 < 0) = %d\n", boolTemp);

    return 0;
}

实践出真知嘛。我还是相信自己试出来的第二种,其输出如下:

c1 value(int)=100, hex code=64
c2 value(int)=-100, hex code=FFFFFF9C
(c1 > 0) && (c2 < 0) = 1
b1 value(int)=100, hex code=64
b2 value(int)=156, hex code=9C
(b1 > 0) && (b2 < 0) = 0

此外,可以在minGW的头文件 rpcndr.h 找到如下的定义:

#define small char
typedef unsigned char byte;
typedef unsigned char boolean;

可以看到这个byte被强制看做一字节处理,并且在转义输出为十六进制时是一个大于零没有符号位的数字;而char是可以存储负数的。总的来说,char有符号,byte无符号,并且byte的定义是混乱的。

Java的一字节?

Java的byte

Java的byte实际上和C++的char是一致的,都是一字节有符号整数。

Java的char

Java的char,居然是两字节!Java的char是无符号的两字节整数,一般用于表示字符。两字节表示空间就大很多,这让它可以编码汉字——利用Unicode。

如果在Java中写这么一段代码,会发现后两行会触发IDE的报错警告(红色波浪线)。

char c1 = 100;
c1 = 65535;
c1 = 65536;     // 报错提示,会溢出
c1 = -100;      // 报错提示,会溢出

小结

C++Java
char有符号的一字节无符号的两字节
byte非关键字,一般是无符号一字节有符号的一字节
两种语言中char和byte关键字的对比