Java使用文本块(TextBlocks)处理多行字符串的操作方法
Java文本块以三个双引号包裹多行文本,自动保留换行与缩进,无需手动拼接或转义。缩进量由结束标记位置决定,支持`\s`、`\`等专属转义符。适用于JSON、SQL、HTML模板等场景,显著提升代码可读性与开发效率。起始标记必须单独一行,否则编译报错。
一、什么是文本块?
文本块(Text Blocks)是Ja va专门用来处理多行字符串的语法。它本质上还是普通字符串(ja va.lang.String),只是写法上做了简化——不是新的数据类型。它的核心玩法,就是用「三个双引号(""")」作为起始和结束标记,把多行文本直接包裹起来。
这样一来,换行、空格等格式都会自动保留,你完全不需要手动加\n,不需要用+拼接,也不用频繁转义双引号。
几个核心优势:
- 简洁高效:直接在代码里按真实格式写,不用拼、不用加转义;
- 可读性强:SQL、JSON、HTML这些代码片段,看一眼就知道是什么结构;
- 减少错误:拼接遗漏、转义出错、换行符缺失这类老问题,基本不会再有了;
- 无缝兼容:它跟普通字符串完全等价,所有String类的API(
length()、replace()、substring()等)都能直接用。
二、基础语法与硬性规则
文本块的语法看起来简单,但有几个硬性规则必须严格遵守,否则编译器会直接报错。这也是新手最容易踩坑的地方,值得仔细看看。2.1 基础语法格式
核心语法只有一个:用三个双引号包裹多行文本。具体的格式要求如下:// 标准格式(推荐)
String 文本块变量名 = """
第一行文本内容
第二行文本内容
第三行文本内容
""";
拆开说明一下:
1. 起始标记:三个双引号,必须单独一行,不能和任何文本内容在同一行。这是硬性要求,违反了直接编译报错。
2. 文本内容:跟在起始标记后面,每行文本可以自由编写。换行不用手动加\n,空格和缩进也都会自动保留。
3. 结束标记:同样三个双引号,可以和最后一行文本放在同一行,也可以单独一行。推荐单独一行,跟起始标记对齐,这样格式更整洁。
4. 缩进要求:文本内容的缩进,以「结束标记的缩进位置」为准。结束标记缩进多少,文本内容左侧的多余缩进就会被去掉多少。这一条是重点,后面会单独细说。
2.2 正确与错误示例对比
// 正确示例1:结束标记单独一行(推荐)
String json = """
{
"id": 1001,
"username": "zhangsan",
"age": 28
}""";
// 正确示例2:结束标记与最后一行文本同一行
String html = """
Ja va文本块
优雅处理多行字符串
""";
// 错误示例1:起始标记与文本内容同一行(编译报错)
String error1 = """Hello World"""; // 报错:非法表达式开始
// 错误示例2:起始标记后无换行(编译报错)
String error2 = """ 第一行文本
第二行文本"""; // 报错:文本块起始标记后必须换行
// 错误示例3:结束标记缺失(编译报错)
String error3 = """
第一行文本
第二行文本; // 报错:未闭合的字符串字面量""";
2.3 文本块与普通字符串的等价性
这一点很重要:文本块本质上就是普通字符串,跟用单个双引号包裹的字符串完全等价。它可以无缝衔接所有String API,运行时性能也完全一致。// 文本块
String textBlock = """
Hello World
Ja va Text Blocks""";
// 普通字符串(等价于上面的文本块)
String normalStr = "Hello World\nJa va Text Blocks";
// 两者完全等价
System.out.println(textBlock.equals(normalStr)); // true
System.out.println(textBlock.length() == normalStr.length()); // true
// 无缝使用String API
String upperStr = textBlock.toUpperCase(); // 转为大写
String subStr = textBlock.substring(0, 5); // 截取子串
boolean contains = textBlock.contains("Ja va"); // 判断包含关系
三、缩进规则
文本块的缩进处理,可以说是最容易出错的环节。很多开发者写出来的文本块格式混乱,说到底就是没搞懂缩进是怎么算的。核心原则只有一句话:文本块最终的缩进 = 编写时的缩进 - 结束标记的缩进。3.1 缩进规则详解
Ja va编译器在处理文本块时,会自动“去除多余缩进”。去除的缩进量,由「结束标记的缩进位置」来决定。具体分3种情况: 1. 结束标记与起始标记缩进一致(推荐):文本内容会去除与起始/结束标记相同的缩进量,保留文本内部的相对缩进; 2. 结束标记缩进比起始标记少:文本内容会去除与结束标记相同的缩进量,剩余的缩进会被保留; 3. 结束标记无缩进:文本内容会保留编写时的全部缩进,容易导致格式混乱,不推荐。3.2 示例
// 示例1:结束标记与起始标记缩进一致(推荐)
// 起始标记缩进4个空格,结束标记也缩进4个空格
String str1 = """
第一行文本(无缩进)
第二行文本(缩进2个空格)
第三行文本(无缩进)
""";
// 最终输出(去除4个空格,保留内部相对缩进):
// 第一行文本(无缩进)
// 第二行文本(缩进2个空格)
// 第三行文本(无缩进)
// 示例2:结束标记缩进比起始标记少(2个空格)
// 起始标记缩进4个空格,结束标记缩进2个空格
String str2 = """
第一行文本
第二行文本
"""; // 结束标记缩进2个空格
// 最终输出(去除2个空格,剩余2个空格缩进):
// 第一行文本
// 第二行文本
// 示例3:结束标记无缩进(不推荐)
// 起始标记缩进4个空格,结束标记无缩进
String str3 = """
第一行文本
第二行文本
"""; // 结束标记无缩进
// 最终输出(保留全部4个空格缩进):
// 第一行文本
// 第二行文本
总结一下:始终保持「起始标记、结束标记缩进一致」,并且与代码块的缩进对齐(比如在方法内部,就与方法体的缩进保持一致)。这样做,文本块的格式最整洁,也最容易维护。
四、转义字符的使用
文本块支持所有Ja va普通字符串的转义字符(如\n、\t、\"等),同时还新增了2个专属转义符,专门用来优化文本块的格式处理,解决一些特殊场景下的问题。
4.1 常用转义字符汇总
转义符 |
作用 |
适用场景 |
示例 |
\n |
手动换行(可省略,文本块自动识别换行) |
需要强制换行,或在单行文本中插入换行 |
"""Hello\nWorld""" → 输出Hello换行World |
\t |
制表符 |
格式化表格、代码片段,实现整齐缩进 |
"""姓名:\t张三\n年龄:\t25""" |
\" |
转义双引号,避免与"""冲突 |
文本中包含双引号(如JSON、HTML标签) |
"""{"name": "Ja va\"TextBlocks\""}""" |
\\ |
转义反斜杠,避免被解析为转义符 |
文本中包含反斜杠(如文件路径、正则表达式) |
"""C:\\Program Files\\Ja va""" |
\s |
代表一个空格(文本块专属,Ja va 14+ 支持) |
需要固定空格,避免手动输入多个空格导致格式混乱 |
"""姓名:\s\s张三""" → 姓名: 张三 |
\ |
取消换行(文本块专属,Ja va 14+ 支持) |
将多行文本合并为一行,避免自动换行 |
"""SELECT id FROM user\ |
4.2 示例:转义字符的常见用法
// 1. 转义双引号(JSON场景)
String json = """
{
"id": 1001,
"username": "zhangsan",
"desc": "Ja va\"文本块\"实战"
}""";
// 2. 取消换行(SQL场景,将多行SQL合并为一行)
String sql = """
SELECT id, name, age \
FROM user \
WHERE age > 18 \
ORDER BY age DESC""";
// 最终输出:SELECT id, name, age FROM user WHERE age > 18 ORDER BY age DESC
// 3. \s 固定空格(格式化输出)
String userInfo = """
姓名:\s\s张三
年龄:\s\s25
职业:\s\s程序员
地址:\s\s北京市海淀区""";
// 4. 转义反斜杠(文件路径场景)
String filePath = """
C:\\Program Files\\Ja va\\jdk1.8.0_301
""";
五、开发场景
文本块的核心价值,就是简化多行字符串的编写。来看看实际开发中最常用的5个场景,覆盖了JSON、SQL、HTML、日志、模板等,基本上可以直接拿来用。场景1:编写JSON字符串
传统写法要手动拼接、转义双引号,代码又长又容易出错。文本块可以直接按JSON格式写,缩进和换行都保留,可读性和可维护性大幅提升。// 文本块写法(优雅简洁)
String userJson = """
{
"id": 1001,
"username": "zhangsan",
"password": "123456",
"age": 28,
"gender": "male",
"address": "北京市海淀区",
"hobbies": ["coding", "reading", "running"],
"status": 1
}""";
// 结合Jackson解析JSON(无缝衔接)
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(userJson, User.class);
System.out.println(user.getUsername()); // 输出:zhangsan
场景2:编写复杂SQL语句
复杂SQL(多表关联、子查询、条件筛选)通常需要换行排版。文本块可以保留SQL的原始格式,避免拼接错误,后期修改时只需要调整对应行就行。// 文本块编写复杂SQL(多表关联)
String sql = """
SELECT
u.id,
u.username,
u.age,
d.department_name,
d.department_address
FROM
user u
LEFT JOIN
department d ON u.department_id = d.id
WHERE
u.age > 18
AND d.department_name LIKE '%技术%'
AND u.status = 1
ORDER BY
u.age DESC
LIMIT 10""";
// 执行SQL(与普通字符串无区别)
PreparedStatement pstmt = connection.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
场景3:生成HTML模板(邮件/静态页面)
在后端生成HTML页面(比如验证码邮件、通知邮件、静态页面)时,文本块可以直接写HTML标签,页面结构一目了然,完全不用手动拼接标签和换行。// 文本块编写HTML邮件模板
String emailTemplate = """
验证码通知
您的验证码已生成
尊敬的用户,您好!您的验证码为:
$[code]
验证码有效期为10分钟,请及时使用,请勿泄露给他人。
本邮件无需回复,如有疑问,请联系客服。
""";
// 替换模板变量(结合String.format)
String emailContent = String.format(emailTemplate, "123456");
场景4:输出多行日志
对于复杂的操作日志,文本块可以保留日志的换行和格式,比传统的单行日志要清晰得多,排查问题时也更有帮助。// 文本块输出多行日志
LocalDateTime now = LocalDateTime.now();
log.info("""
用户操作日志详情:
操作时间:{}
操作人:zhangsan
操作ID:OP20240519001
操作类型:查询用户信息
操作参数:{id: 1001}
操作结果:成功
响应时间:50ms
备注:无异常""", now);
场景5:编写多行注释/接口说明
对于复杂的接口说明或方法注释,文本块可以保留换行和格式,比传统的多行注释更灵活,也可以用于生成接口文档的描述信息。// 文本块编写接口说明
String apiDesc = """
接口名称:查询用户信息接口
接口路径:/api/user/getById
请求方式:GET
请求参数:
id:Integer,必填,用户ID
响应参数:
id:Integer,用户ID
username:String,用户名
age:Integer,年龄
address:String,地址
异常说明:
1. ID为null或小于0,返回400参数错误
2. ID不存在,返回404用户不存在
3. 系统异常,返回500服务器错误
备注:该接口需登录后访问,携带Token""";
六、注意事项
文本块语法简单,但细节上容易出错。下面这几个是在开发中最常见的坑点,附带了错误示例和正确写法,帮你避开所有陷阱。坑1:起始标记与文本内容在同一行(编译报错)
// 错误示例
String error = """Hello World""";
// 编译报错:illegal start of expression
// 正确示例
String correct = """
Hello World""";
坑2:缩进处理不当,导致格式混乱
// 错误示例(结束标记无缩进)
String str = """
第一行文本
第二行文本
"""; // 结束标记无缩进
// 最终输出会保留全部4个空格缩进,格式混乱
// 正确示例(结束标记与起始标记缩进一致)
String str = """
第一行文本
第二行文本
""";
// 最终输出格式整洁
坑3:忘记转义双引号,导致语法冲突
// 错误示例
String json = """
{
"name": "Ja va"TextBlocks"" // 双引号未转义,与"""冲突
}"""; // 编译报错
// 正确示例
String json = """
{
"name": "Ja va\"TextBlocks\""
}""";
坑4:误认为文本块支持直接变量插值
Ja va文本块不支持直接的变量插值(比如${variable})。很多开发者习惯了其他语言的做法,会误以为文本块也支持,结果变量没有被替换。
// 错误示例(变量插值无效)
String name = "zhangsan";
String str = """
姓名:${name}
年龄:25"""; // 输出:姓名:${name},不会替换变量
// 正确示例(结合String.format()替换变量)
String str = String.format("""
姓名:%s
年龄:%d""", name, 25);
// 或者使用Apache Commons Text的StringSubstitutor
StringSubstitutor substitutor = new StringSubstitutor(Map.of("name", "zhangsan", "age", "25"));
String str = substitutor.replace("""
姓名:${name}
年龄:${age}""");
坑5:文本块末尾多留空行
如果结束标记单独一行,且与最后一行文本之间留了空白行,那么blank行会被保留在文本块中,可能导致格式异常,比如JSON解析失败或SQL语法错误。// 错误示例(结束标记前多留空行)
String json = """
{
"id": 1001,
"name": "zhangsan"
}
""";
// 正确示例(结束标记与最后一行文本紧密衔接)
String json = """
{
"id": 1001,
"name": "zhangsan"
}""";
八、全文总结
Ja va文本块是一款“小而美”的语法。它的核心价值在于「简化多行字符串编写」——不用手动拼接,不用加换行符,不用频繁转义,让SQL、JSON、HTML等多行文本的编写变得优雅、高效。 掌握文本块的关键在于:牢记起始标记单独一行、理解缩进规则、会用转义技巧,并且避开那几个常见的坑点。同时要明白,文本块与普通字符串完全等价,可以无缝衔接现有String API。 在实际开发中,只要涉及多行字符串,优先考虑文本块。它不仅减少了代码量、降低了错误率,也让代码的可读性和可维护性上了一个台阶。对于Ja va开发者来说,这绝对是一个值得熟练掌握的实用语法。
Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。
















