Java 语言中一个字符占几个字节?
Java中理论说是一个字符(汉字 字母)占用两个字节。
但是在UTF-8的时候 new String("字").getBytes().length 返回的是3 表示3个字节
作者:RednaxelaFX
链接:https://www.zhihu.com/question/27562173/answer/37188642
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题主要区分清楚内码(internal encoding)和外码(external encoding)就好了。内码是程序内部使用的字符编码,特别是某种语言实现其char或String类型在内存里用的内部编码;外码是程序与外部交互时外部使用的字符编码。“外部”相对“内部”而言;不是char或String在内存里用的内部编码的地方都可以认为是“外部”。例如,外部可以是序列化之后的char或String,或者外部的文件、命令行参数之类的。Java语言规范规定,Java的char类型是UTF-16的code unit,也就是一定是16位(2字节);char, whose values are 16-bit unsigned integers representing UTF-16 code units (§3.1).然后字符串是UTF-16 code unit的序列:The Java programming language represents text in sequences of 16-bit code units, using the UTF-16 encoding.这样,Java规定了字符的内码要用UTF-16编码。或者至少要让用户无法感知到String内部采用了非UTF-16的编码。“感知”可以是多方面的,例如随机访问某个下标的code unit(String.charAt())应该是O(1)操作,这只有使用UTF-16或者别的“定长”编码才可以做到。注意我这里说的“定长”特指code unit定长,而不是说code point定长。String.getBytes()是一个用于将String的内码转换为指定的外码的方法。无参数版使用平台的默认编码作为外码,有参数版使用参数指定的编码作为外码;将String的内容用外码编码好,结果放在一个新byte[]返回。题主的例子里,显然外码是UTF-8,那么调用了String.getBytes()之后得到的byte[]只能表明该外码的性质,而无法碰触到String内码的任何特质。另举一例:Java标准库实现的对char与String的序列化规定使用UTF-8作为外码。Java的Class文件中的字符串常量与符号名字也都规定用UTF-8编码。这大概是当时设计者为了平衡运行时的时间效率(采用定长编码的UTF-16)与外部存储的空间效率(采用变长的UTF-8编码)而做的取舍。题外话1:可惜UTF-16在Java设计之初还是真的定长编码,后来Unicode涵盖的字符变多了之后UTF-16变成了坑爹的变长编码(一个完整的“字符”是一个code point;一个code point可以对应1到2个code unit;一个code unit是16位),Java也只好跟进。为了实现UTF-16的变长编码语义,Java规定char仍然只能是一个16位的code point,也就是说Java的char类型不一定能表示一个UTF-16的“字符”——只有只需1个code unit的code point才可以完整的存在char里。但String作为char的序列,可以包含由两个code unit组成的“surrogate pair”来表示需要2个code unit表示的UTF-16 code point。为此Java的标准库新加了一套用于访问code point的API,而这套API就表现出了UTF-16的变长特性。题外话2:前面我说Java的内码时说得比较松,留下了“不总是使用UTF-16作为内码,但是用户无法感知区别”的余地。在Sun JDK6中有一个“压缩字符串”(-XX:+UseCompressedString)的功能。启用后,String内部存储字符串内容可能用byte[],也可能用char[];当整个字符串所有字符都在ASCII编码范围内时,就使用byte[](ASCII序列)来存储,此时字符串就处于“压缩”状态;反之,只要有任何一个字符超出了ASCII的编码范围,就退回到用char[](UTF-16序列)来存储。ASCII编码也是一种定长编码,而且其涵盖的字符是UTF-16的真子集;用户在对一个“压缩”的字符串访问其内容时(例如String.charAt()),只需对ASCII字符做无符号扩展就可以得到对应的UTF-16 code unit。这样用户也就无法感知到Java String的内码不是UTF-16的情况。Sun JDK6对“压缩字符串”的实现不够理想,实现太复杂而效果未如预期的好,所以没有包含在OpenJDK6、Oracle JDK7/OpenJDK7里。现在Oracle在重新审视“压缩字符串”功能,有可能在JDK9重新实现出来。题外话3:同样规定使用UTF-16作为内码的JavaScript语言,其实现广泛应用了“压缩字符串”的思想。现在主流的JavaScript引擎都会尽可能用ASCII内码的字符串,不过用户能接触的API只能看到UTF-16 code unit。
Java 语言中一个字符占几个字节?的更多相关文章
- utf-8的中文,一个字符占几个字节
https://blog.csdn.net/kindsuper_liu/article/details/80202150 英文字母和中文汉字在不同字符集编码下的字节数英文字母:·字节数 : 1;编码: ...
- utf-8的中文是一个字符占几个字节
utf-8的中文是一个字符占几个字节 英文字母和中文汉字在不同字符集编码下的字节数英文字母:·字节数 : 1;编码:GB2312 字节数 : 1;编码:GBK 字节数 : 1;编码:GB18030 字 ...
- ORACLE中一个字符占多少字节?
问题描述 或许你会说一个中文字符占2个字节,这是一定的?如何计算一个字符串的字节数? 解决方案 在oracle中一个字符特别是中文占几个字节是不同的. 比如我创立一个表create table tes ...
- C语言中一个字符对应一个ascii码;占一个1个字节8个二进制位;存到内存中也是用ascii的十进制的二进制表示
/** 只读变量和常量 const 只读 const int a; int const a;//同上面的代码行是等价的,都表示一个常整形数. int *const a;//const具有"左 ...
- C语言中一个字符数组里面的所有元素变成一个字符串
#include <string.h> int main() // 这里为了方便直接用main函数 { char array[] = { 'h', 'e', 'l', 'l', ' ...
- php中一个字符占用几个字节?
先看看字符与字节有什么区别: (一)“字节”的定义 字节(Byte)是一种计量单位,表示数据量多少,它是计算机信息技术用于计量存储容量的一种计量单位. (二)“字符”的定义 字符是指计算机中使用的文字 ...
- Java语言中的正则表达式
正则表达式是什么? 正则表达式是一种强大而灵活的文本处理工具.初学正则表达式时,其语法是一个难点,但它确实是一种简洁.动态的语言.正则表达式提供了一种完全通用的方式,能够解决各种字符串处理相关的问题: ...
- JAVA语言中的修饰符
JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...
- Java语言中的面向对象特性总结
Java语言中的面向对象特性 (总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知 ...
随机推荐
- Snmp在Windows下的实现----WinSNMP编程原理
在Windows 下实现SNMP协议的编程,可以采用Winsock接口,在161,162端口通过udp传送信息.在Windows 2000中,Microsoft已经封装了SNMP协议的实现,提供了一套 ...
- 洛谷P4092树——并查集
题目:https://www.luogu.org/problemnew/show/P4092 利用并查集,倒序离线,那么从倒序来看被撤销标记的点就再也不会被标记,所以用并查集跳过: 莫名其妙的WA,调 ...
- ceph部署与问题
一.基本情况:物理设备:4台惠普dl360,4个千兆网卡 4个1T盘操作系统统一为:CentOS 7.2.1511ceph版本:10.2.3ceph-deploy版本:1.5.36网络情况:192.1 ...
- Java--23种设计模式之decorator模式
装饰模式:装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性.动态给一个对象增加功能,这些功能可以再动态的撤消.增加由一些基本功能的排列组合而产生的非常大量的 ...
- DispatcherServlet详解
1.1.DispatcherServlet作用 DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring Io ...
- CF-805A
A. Fake NP time limit per test 1 second memory limit per test 256 megabytes input standard input out ...
- java集合框架之比较器Comparator、Comparable
参考http://how2j.cn/k/collection/collection-comparator-comparable/693.html Comparator 假设Hero有三个属性 name ...
- Identity Server 4 原理和实战(完结)_Resource Owner Password Credentials 授权实例
今天要讲的 用fiddler来监听,昨天的客户端的请求 这是一个post的请求 这是响应的数据 Expores_in超时时间, 今天的内容 在服务端再声明一个client端 wpf的应用的效果图 首先 ...
- Swift3.0 Alamofire网络请求的封装(get,post,upload图片上传)转
转自: http://blog.csdn.net/C_calary/article/details/53193747 学习Swift 试着动手写个天气小app,搜集资料这个封装还蛮好用的. 我用的第三 ...
- jzoj5988. 【WC2019模拟2019.1.4】珂学计树题 (burnside引理)
传送门 题面 liu_runda曾经是个喜欢切数数题的OIer,往往看到数数题他就开始刚数数题.于是liu_runda出了一个数树题.听说OI圈子珂学盛行,他就在题目名字里加了珂学二字.一开始liu_ ...