能存储多少字符,通过以下步骤来看

  1. 首先String的length方法返回是int。所以理论上长度一定不会超过int的最大值。
  2. 编译器对字符串字面量长度的限制源自Java编译器(如javac)在处理常量池时的实现。编译器源码如下,限制了字符串长度大于等于65535就会编译不通过:
    // src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java
    public class Pool {
    // ... /**
    * Add a new Utf8 string to the constant pool, checking for duplicates
    * and sharing the entry if one already exists.
    */
    public int putUtf8(String x) {
    Assert.checkNonNull(x);
    byte[] bytes;
    try {
    ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
    DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream);
    dataoutputstream.writeUTF(x);
    dataoutputstream.close();
    bytes = bytearrayoutputstream.toByteArray();
    } catch (IOException e) {
    throw new AssertionError(e);
    }
    if (bytes.length > 65535)
    throw new UTFDataFormatException("encoded string too long: " + bytes.length + " bytes");
    return put(new Pool.Utf8Entry(bytes));
    } // ...
    }

Java中的字符常量都是使用UTF 8编码的,UTF 8编码使用1~4个字节来表示具体的Unicode字符。所以有的字符占用一个字节,而平时所用的大部分中文都需要3个字节来存储。

//65534个字母,编译通过
String s1 = "dd..d"; //21845个中文”自“,编译通过
String s2 = "自自...自"; //一个英文字母d加上21845个中文”自“,编译失败
String s3 = "d自自...自";
  • 对于s1,一个字母d的UTF8编码占用一个字节,65534个字母占用65534个字节,长度是65534,长度和存储都没超过限制,所以可以编译通过。

  • 对于s2,一个中文占用3个字节,21845个正好占用65535个字节,而且字符串长度是21845,长度和存储也都没超过限制,所以可以编译通过。

  • 对于s3,一个英文字母d加上21845个中文”自“占用65536个字节,超过了存储最大限制,编译失败。

当然,这个限制是特定于编译器的实现,而不是Java语言本身的限制。

  1. JVM规范对常量池有所限制。

量池中的每一种数据项都有自己的类型。Java中的UTF-8编码的Unicode字符串在常量池中以CONSTANTUtf8类型表示。CONSTANTUtf8的数据结构如下:

CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}

重点关注长度为 length 的那个bytes数组,这个数组就是真正存储常量数据的地方,而 length 就是数组可以存储的最大字节数,而不是字符数。length 的类型是u2,u2是无符号的16位整数,因此理论上允许的的最大长度是2^16-1=65535。所以上面byte数组的最大长度可以是65535。

当然,考虑到UTF-8是一种变长编码,一个字符可能需要1到4个字节来表示(取决于字符的具体值)。因此,如果你的字符串包含大量使用多个字节编码的字符,那么它能包含的实际字符数将会少于65535。

  1. 运行时限制

String 运行时的限制主要体现在 String 的构造函数上。下面是 String 的一个构造函数:

public String(char value[], int offset, int count) {
...
}

上面的count值就是字符串的最大长度。在Java中,int的最大长度是2^31-1。所以在运行时,String 的最大长度是2^31-1。

但是这个也是理论上的长度,实际的长度还要看JVM的内存。来看下,最大的字符串会占用多大的内存。

(2^31-1)*16/8/1024/1024/1024 = 2GB

所以在最坏的情况下,一个最大的字符串要占用4GB的内存。如果JVM不能分配这么多内存的话,会直接报错的。

总结

因此,主要的还是看编译器对常量池的限制,使得byte数组的最大长度不能超过65535;以及JVM的内存限制

补充:JDK9以后对String的存储进行了优化。底层不再使用char数组存储字符串,而是使用byte数组。对于LATIN1字符的字符串可以节省一倍的内存空间。详情请看 Java9 - string字符串的变化

关于作者

来自一线程序员Seven的探索与实践,持续学习迭代中~

本文已收录于我的个人博客:https://www.seven97.top

公众号:seven97,欢迎关注~

String究竟能存储多少字符?的更多相关文章

  1. Java中String对象的存储位置(学习笔记)

    首先,String是final修饰的.immutable对象,它以一个个字符的方式存储在字符数组中.其次,String类型创建对象有两种方式:①通过字面量赋值:会先去常量池中查找是否存在相同的字符串, ...

  2. MySQL 存储表情字符

    摘要 在 MySQL 中直接存储表情的时候,会出现无法插入数据的错误. 这是由于一般情况下,MySQL 的字符集是 utf8,而对于 emoji 表情的 mysql 的 utf8 字符集是不支持,需要 ...

  3. mysql 无法存储表情字符 java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\xBE",...' for column 'XXXX' at row 1

    1.变更字段类型 ALTER TABLE api_log MODIFY COLUMN remark longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_uni ...

  4. java中String常量的存储原理

    相关题目(运行结果在代码注释后面) 1. package StringTest; public class test1 { public static void main(String[] args) ...

  5. 为什么 char 数组比 String 更适合存储密码?

    推荐阅读:5 个刁钻的 String 面试题! 另一个基于 String 的棘手 Java 问题,相信我只有很少的 Java 程序员可以正确回答这个问题. 这是一个真正艰难的核心 Java 面试问题, ...

  6. String与基本类型,字符数组,字节数组的转换

    String与基本数据类型 * 基本数据 --->字符串(String) * 1.基本数据类型值 +"" --->最简单 * 2.使用包装类中的toString(参数类 ...

  7. 为什么 char 数组比 Java 中的 String 更适合存储密码?

    另一个基于 String 的棘手 Java 问题,相信我只有很少的 Java 程序员可以正确回答这个问题.这是一个真正艰难的核心Java面试问题,并且需要对 String 的扎实知识才能回答这个问题. ...

  8. [LeetCode] First Unique Character in a String 字符串第一个不同字符

    Given a string, find the first non-repeating character in it and return it's index. If it doesn't ex ...

  9. [CareerCup] 1.1 Unique Characters of a String 字符串中不同的字符

    1.1 Implement an algorithm to determine if a string has all unique characters. What if you cannot us ...

  10. XML中文本节点存储任意字符的方法

    XML xml是一种可扩展标签语言, 为众多浏览器支持解析, ajax更是利用xml来完成服务器和客户端之前的通信. xml基本元素为 <label>xxx</label>, ...

随机推荐

  1. matlab常用语法简介

    目录 一.输入函数 1.disp函数 二.合并字符串 1.strcat函数 (1)strcat函数可用于合并字符串,用法如图: 2.利用向量,用法如图: 3.利用"num2str" ...

  2. Java FastJson解析json字符串

    json转map Map<String, 实体类> titleMap=JSON.parseObject(JSON字符串, new TypeReference<HashMap<S ...

  3. 直播预告:Service Mesh 技术在美团的落地和挑战

    一场突如其来的疫情加深了企业对数字化转型升级的渴望,作为新兴数字化业务的基础,云原生技术的价值日益凸显.当前,越来越多的企业逐步引入容器.微服务/Service Mesh 技术改造业务,实现数据库.P ...

  4. 在Django中查找重复项目

    在Django中查找重复项目通常涉及使用查询集(QuerySet)和模型(Model).假设你有一个模型,比如Item,你想查找其中重复的项目,可以通过以下步骤来实现: 确定重复的标准: 首先需要确定 ...

  5. C# LINQ之IEqualityComparer<>接口应用

    在C#语言中,对集合的条件查询.分组统计等操作使用LINQ非常方便,LINQ的语法格式与SQL非常相似和便捷,而LINQ扩展方法配合Lambda更为简洁,如All.Any.Count.Max等Enum ...

  6. SMU Summer 2024 Contest Round 3(7.10)zhaosang

    打的最菜一次,最惨一次,题读假了 A-A http://162.14.124.219/contest/1007/problem/A 签到题 要解决这道题,素数对,数据量不是很大,所以我们可以先预处理素 ...

  7. VUE系列之性能优化--懒加载

    一.懒加载的基本概念 懒加载是一种按需加载技术,即在用户需要时才加载相应的资源,而不是在页面初始加载时一次性加载所有资源.这样可以减少页面初始加载的资源量,提高页面加载速度和用户体验. 二.Vue 中 ...

  8. Zabbix 5.0 LTS 配置企业微信(Webhook)自动发送告警信息

    依据前面文章<Zabbix 5.0 LTS URL 健康监测>环境,实现企业微信(Webhook)自动发送告警信息. 一.创建企业微信机器人 先在自己的企业微信群里创建一个机器人,并获取其 ...

  9. C#/.NET/.NET Core优秀项目和框架2024年7月简报

    前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍.功能特点.使用方式以及部分功能截图 ...

  10. 2、SpringMVC之入门案例

    2.1.环境搭建 2.1.1.右击project创建新module 2.1.2.选择maven 2.1.3.设置module名称和路径 2.1.4.module初始状态 2.1.5.配置打包方式 注意 ...