本文部分内容摘抄自:《算法》第四版,图灵丛书,人邮出版社
序
孔老师:茴香豆的茴字有四种写法,来,我告诉你。
1、一道面试题
String str = "搞java";占用多少内存空间?一般给的答案是“6字节”。然而凭着男人的直觉,这个答案貌似不完全正确。
如下图示:
这6个字节是如何来的?看这里,上干货fuck goods
import java.io.UnsupportedEncodingException;
public class StringTest {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "搞java";
System.out.println("\"搞java\".length():" + (str.length()));
System.out.println("\"搞java\".getBytes().length:" + (str.getBytes().length));
System.out.println("\"搞java\".getBytes(\"GBK\").length:" + (str.getBytes("GBK").length));
System.out.println("\"搞java\".getBytes(\"UTF-8\").length:" + (str.getBytes("UTF-8").length));
/**
* "搞java".length():5
"搞java".getBytes().length:6
"搞java".getBytes("GBK").length:6
"搞java".getBytes("UTF-8").length:7
*/
}
}
6个字节的来源是getByte().length。
2、看源码解释方法
String.length()方法,返回一个和该字串的uinicode单位数量相同的长度,就是字串的长度。"搞java"中一共有5个单位的unicode码,返回5,注意这个方法并不是该字串所占用的存储空间
/**
* Returns the length of this string.
* The length is equal to the number of <a href="Character.html#unicode">Unicode
* code units</a> in the string.
*
* @return the length of the sequence of characters represented by this
* object.
*/
public int length() {
return count;
}
String.getBytes()方法,使用平台默认字符集,将该字串编码成字节序列,将结果搞到一个byte数组中。是的,是平台默认字符集,也就是不同的字符集,将会产生不同的字节序列。"GBK"编码中,1个汉字2个字节,一个ASC2是1个字节,"搞java"是6个byte;"utf-8"码中,1个汉字将占用3个字节,1个ASC2是1个字节,"搞java"就是7个byte
/**
* Encodes this {@code String} into a sequence of bytes using the
* platform's default charset, storing the result into a new byte array.
*
* <p> The behavior of this method when this string cannot be encoded in
* the default charset is unspecified. The {@link
* java.nio.charset.CharsetEncoder} class should be used when more control
* over the encoding process is required.
*
* @return The resultant byte array
*
* @since JDK1.1
*/
public byte[] getBytes() {
return StringCoding.encode(value, offset, count);
}
结论:length()方法不能表示占用存储空间;getByte()方法和平台默认字符集有关不靠谱,"GBK"字符集下将会编码成6个byte,其他字符集就未必了。
3、真相极其残酷,String对象所占的内存空间
3.1、对象所使用的空间,
•对象头(object header):32位机8 个字节(保存对象的 class 信息、ID、在虚拟机中的状态),64位机器16字节
•Java 原始类型数据:如 int, float, char 等类型的数据,参看表1
•引用(reference):在32位系统上每个占用4bytes, 在64位系统上每个占用8bytes
•填充符(padding):一般内存的使用会被填充为8的倍数
表 1. Java 各数据类型所占内存
boolean | 1 |
byte | |
char | 2 |
short | |
int | 4 |
float | |
long | 8 |
double |
3.2数组所占用内存空间
java中数组被实现为对象,因为记录长度而需要额外的内存。一个原始数据类型的数组一般需要24字节头信息(16个字节的对象开销,4字节保存长度,4字节填充字)再加上保存值所需要的内存。例如:1个N个int的数组,需要使用(24+4N)字节,一个int占4字节;一个含有N个double的数组,需要(24+8N),一个double占8字节;
3.3空字串所占内存空间
如果对于 String(JDK 6)的成员变量声明如下:
private final char value[];
private final int offset;
private final int count;
private int hash;
如何计算该 String 所占的空间?String对象内存+3个int属性内存+1个char[]内存,就是这么计算
先计算空的 char 数组所占空间:
<64位机>16(对象开销)+ 4(保存长度) + 2*0(一个char是2字节,共有0个char)=20byte,再给padding使之成为8的倍数,就是20 + 4 = 24字节
<32位机>8(对象开销) + 4 (保存长度) + 2*0=12字节,填充一下就是12+4=16 字节
那么一个空 String 所占空间为:
<64位机>16(对象开销) + 12字节(3个int,1个int占4字节) + 8(char[]引用) + 24(空char[]) = 60字节
不要忘了填充,60 + 4 = 64字节
<32位机>8(对象开销) + 12字节(3个int) + 4(char[]引用) + 16(空char[]) = 40字节
结论,String对象所占内存空间大约为
N是String对象char数组的长度,注意这里说的的char[]数组的长度,而不是String.length()
<64位机> 2*N + 64 + padding,这么多的字节byte
<32位机> 2*N + 40 + padding,这么多的字节byte
现在回过头来看面试题,String str = "搞java";占用多少内存空间?一般给的答案是“6字节”。然而这个答案一定完全不正确。
结束的时候,留一个悬疑,敬请关注下篇:String那点事儿3--溢出、陷阱、效率、优化
相关推荐
api-ms-win-crt-string-l1-1-0
api-ms-win-core-string-l1-1-0.dll
001-glib-gdate-suppress-string-format-literal-warning.patch 001-glib-gdate-suppress-string-format-literal-warning.patch 001-glib-gdate-suppress-string-format-literal-warning.patch
`string-width`是一个Node.js模块,专门用于计算字符串的视觉宽度,即在终端上实际占用的列数。这个功能对于创建美观且对齐的命令行界面至关重要,因为它能够正确处理全宽字符、多字节字符(如UTF-8编码的中文字符)...
StringReader的用法---马克-to-win java视频字符串输入流的介绍
CSLFX-string-input-compare-outresult-03.CPP
ember-string-fns 该插件为Ember模板和组件提供了字符串帮助器。 安装: ember install ember-string-fns 用法 string-last-index-of string-not-equals string-pad-end string-pad-start string-repeat ...
java文档String和StringTokenizer 马克-to-win java视频 字符串解析器
离线安装包,亲测可用
c语言入门 C语言_leetcode题解之08-string-to-integer-atoi.c
String 马克-to-win java视频 字符串的详细描述介绍
js js_leetcode题解之8-string-to-integer-(atoi).js
本篇文章将深入探讨`string-array`和`integer-array`的用法,以及如何在XML中定义和使用它们。 首先,`string-array`是Android中用于存储字符串数组的资源。在Android的资源XML文件(通常位于res/values/strings....
java-string-similarity, 各种字符串相似性和距离算法 java-string-similarity 实现不同字符串相似度和距离度量的库。 目前已经实现了许多算法( 包括Levenshtein编辑距离和 sibblings,jaro winkler,最长公共子序列...