全面瓦解#Java中char型变量到底能不能存储一个汉字问题?

本文深入探讨Java中char型变量是否能存储一个汉字的问题,分析了Unicode与UTF-8编码机制,解释了char类型在不同编码下表示汉字的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在很多面试题中,都会频率出现一道简答题“在Java中,char型变量中能不能存储一个汉字?”,我们条件反射就会想到Java#8种基本数据类型,常规思维就是char占内存(2个字节),在utf-8中汉字占3个字节,明显不够!有刷题的朋友,显然就知道是可以的!但是大部分人还是知其然而不知其所以然,其实这种习惯不是很好。具体什么情况,我查阅了部分的资料,对常见编码进行了详细的分析,对上述的问题也进行了解剖。

数据类型字节默认值
byte10
short20
int40
long80
float40.0f
double80.0d
char2‘\u0000’
boolean4false
常规答案:

能,因为Java中使用的是Unicode编码集,采用两个字节来表示一个字符,每一个字符使用Unicode编码表示。

耐心看完全篇,答案就在下面,一定收获满满!☟

官方解释:

计算机编码指电脑内部代表字母或数字的方式.常见的编码方式有:ASCII编码,GB2312编码(简体中文),GBK,BIG5编码(繁体中文),ANSI编码,unicode,utf-8编码等

①Unicode 编码采用两个字节来表示一个字符,是一种16 位编码方式。目前Unicode 码在全球范围的信息交换领域均有广泛的应用。(即Unicode码是一种国际标准编码,采用二个字节编码)

②UTF,是UnicodeTransformationFormat的缩写,意为Unicode转换格式。

如果UNICODE字符由2个字节表示,则编码成UTF-8很可能需要3个字节,而如果UNICODE字符由4个字节表示,则编码成UTF-8可能需要6个字节。用4个或6个字节去编码一个UNICODE字符可能太多了,但很少会遇到那样的UNICODE字符。

③GBK全称《汉字内码扩展规范》(GBK即“国标”、“扩展”汉语拼音的第一个字母,英文名称:Chinese Internal Code Specification)

经实际测试和查阅文档,GBK是采用单双字节变长编码,英文使用单字节编码,完全兼容ASCII字符编码,中文部分采用双字节编>。(编码方式)

附加:
在这里插入图片描述

代码演示1
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
public class Coding0110Lin {
	private static byte[] getBytesByUTF8(char c) {
		Charset charset = Charset.forName("utf-8");
		CharBuffer charBuffer = CharBuffer.allocate(1);
		charBuffer.put(c);
		charBuffer.flip();
		ByteBuffer byteBuffer = charset.encode(charBuffer);
		return byteBuffer.array();
	}
	private static byte[] getBytesByGBK(char c) {
		Charset charset = Charset.forName("GBK");
		CharBuffer charBuffer = CharBuffer.allocate(1);
		charBuffer.put(c);
		charBuffer.flip();
		ByteBuffer byteBuffer = charset.encode(charBuffer);
		return byteBuffer.array();
	}

	public static void main(String[] args) {
		char letter = 'L';
		char chinese= '林';
        //System.out.println("获取eclipse环境编码"+System.getProperty("file.encoding")); -utf-8
		System.out.println("UTF8编码(环境编码)下char值:");
		System.out.println("英文字符["+letter+"]所占字节长度:"  + getBytesByUTF8(letter).length);
		System.out.println("中文字符["+chinese+"]所占字节长度:"  + getBytesByUTF8(chinese).length);
		System.out.println("GBK编码(默认编码)下char值:");
		System.out.println("英文字符["+letter+"]所占字节长度:" + getBytesByGBK(letter).length);
		System.out.println("中文字符["+chinese+"]所占字节长度:" + getBytesByGBK(chinese).length);	
	}

输出结果:

UTF8编码(环境编码)下char值:
​ 英文字符[L]所占字节长度:1
中文字符[林]所占字节长度:3
GBK编码(默认编码)下char值:
​ 英文字符[L]所占字节长度:2
中文字符[林]所占字节长度:2

应用方法:

①static ByteBuffer allocate(int capacity) :分配一个新的字节缓冲区。新缓冲区的位置将为零,其界限将为其容量,其标记是未定义的。它将具有一个底层实现数组,且其数组偏移量将为零。

② ByteBuffer encode(CharBuffer cb) : 将此 charset 中的 Unicode 字符编码成字节的便捷方法。

③public abstract CharBuffer put(char c): 相对 put 方法(可选操作)。 将给定字符写入此缓冲区的当前位置,然后该位置递增。

④static Charset forName(String charsetName) : 返回指定 charset 的 charset 对象。

分析结果:

从输出结果可以查看,char类型是可以表示一个中文字符的,其类型所占的字节数与编码的类型有关系。

对于中文字符,在UTF-8编码下占3个内存的字节数,在GBK编码下占2个内存的字节数;

对于英文字符,在UTF-8编码下占1个内存的字节数,在GBK编码下占2个内存的字节数;

小结:

(1)在GBK编码下,字符(英文&中文)都是占2个字节的内存,其实这就是char型变量中能存储一个汉字的主要原因,因为Java中使用的是Unicode编码集,采用两个字节来表示一个字符

(2)在UTF-8编码下,字符字节数是进行转换的,也就是上面<官方解释(概念截取)>中②的说法,所以我们常说char类型占有2个字符的内存空间,中文字符占3个字节内存,英文字符占1个字符(一般认为),这也是我们错觉理解char型变量中不能存储一个汉字主要原因,其实是我们没有实质性的理解Unicode与UTF-8之间转换的机制。

如果UNICODE字符由2个字节表示,则编码成UTF-8很可能需要3个字节

拓展思考

分析结果中【英文字符占有、2个字节的内存】明显与<官方解释(概念截取)>中③的说法相矛盾,怎么回事???

经实际测试和查阅文档,GBK是采用单双字节变长编码,英文使用单字节编码,完全兼容ASCII字符编码,中文部分采用双字节编码。

问题延伸

☛编码GBK中字符到底是一个还是两个字节?

百度一下,我进行了筛选:

单字节00–7F这个区间和ASCII是一样的,双字节字符的第一个字节在81-FE之间,通过区别可以判断是单字节还是双字节。

在这里插入图片描述

看完之后还是很蒙…  就如看到这个字“龘”,所以进行代码验证!

代码演示2
public class Coding0110Lin2 {

	public static void main(String[] args) throws UnsupportedEncodingException {
		   String letter="L";//半角
	       String chinese="林";
	       String str="a";//全角的字符
		   System.out.println("(1)UTF8编码(环境编码)下String类型中char:");
	       System.out.println("英文字母["+letter+"]所占字节长度:"+letter.getBytes("utf-8").length);
	       System.out.println("中文字母所占字节长度:"+chinese.getBytes("utf-8").length);
	       System.out.println("(2)GBK编码(默认编码)下String类型中char:");
	       System.out.println("英文字母["+letter+"]所占字节长度:"+letter.getBytes("GBK").length);
	       System.out.println("中文字母["+chinese+"]所占字节长度:"+chinese.getBytes("GBK").length);
	       System.out.println("英文字母(全角)["+str+"]所占字节长度:"+str.getBytes("GBK").length);

	}
}
输出结果:

(1)UTF8编码(环境编码)下String类型中char:
英文字母[a]所占字节长度:1
中文字母所占字节长度:3
(2)GBK编码(默认编码)下String类型中char:
英文字母[a]所占字节长度:1
中文字母[中]所占字节长度:2
英文字母(全角)[a-阿尔法]所占字节长度:2

分析结果:

从输出结果可以看出,在编码UTF8&GBK编码下String中的英文字符都只占个1字节长度,占一个字节不符合常规啊,这里就是其实引入了半角与全角的概念,原来如此。

在GBK编码下,都是采用全角形式(即一个字符用两个字节表示),letter=”a”;中的a是半角输入(ASCII码),str=”a”中的a(阿尔法)是全角,所以占两个字节的。

官方解释:

全角指一个字符占用两个标准字符位置的状态。汉字字符和规定了全角的英文字符及国标GB2312-80中的图形符号和特殊字符都是全角字符

一般的系统命令是不用全角字符的,只是在作文字处理时才会使用全角字符。

全角和半角区别

全角就是字母和数字等与汉字占等宽位置的字。

半角就是ASCII方式的字符,在没有汉字输入法起作用的时候输入的字母数字和字符都是半角的。

示例如下:(键盘的输入是一样的,输入法的设置不同)

[全角举例]AaBb1234@#%&

[半角举例]AaBb1234@#%&;,.:

在汉字输入法出现的时候,输入的字母数字默认为半角,但是标点则是默认为全角(如下图)可以通过鼠标点击输入法工具条上的相应按钮来改变,输入法名字左边的按钮是改变中文和英文输入的,右边的圆和半圆是改变字母和数字的全角半角的,再右边的“.,”或者"。,"是用来改变标点符号的中英文设置(中文标点即是全角,英文标点即是半角),最右边的键盘图标是显示软键盘用的,可以输入一些特殊字符或者其它语言里面的字母。

所以,大家明白了吗?


参考网址:

【1】https://baike.baidu.com/item/字节/1096318
【2】https://baike.baidu.com/item/全角/9323113?fr=aladdin


#轻松一刻

在这里插入图片描述

☝上述分享来源个人总结,如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!

☞本人博客:https://coding0110lin.blog.youkuaiyun.com/  欢迎转载,一起技术交流吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值