注意:JDK9(印象中对底层容器做了改动,由char数组变成了byte数组,节约了内存空间),JDK11已经变了,JDK8是char[]数组,所以对应的equals比较方法也做了改变

split以竖线分割时注意事项

竖线前需要添加双反斜杠才能以竖线分割符切分,同理如果以双竖线切分时,每个竖线以双斜杠开头,示例如下:

1
2
3
4
5
6
7
String aaa = "111|2222|333";
//竖线前面需跟双反斜杠
String[] splits = aaa.split("\\|");

String bbb = "111||222||333"
//每个竖线前面需跟双反斜杠
String[] doubleSplits = bbb.split("\\|\\|");

按编码集的字节长度截取字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static String subStringByBytes(String s,int num, String encodeName){

if(s.length()>num){
s = s.substring(0, num);
}
int byteLength = 0;
try {
byteLength = s.getBytes(encodeName).length;
if(byteLength > num){
s = s.substring(0, s.length() - 1);
s = subStringByBytes(s, num, encodeName);
}
} catch (UnsupportedEncodingException e) {
log.error("subStringByBytes error, s = {}, num = {}");
}

return s;
}

带*符号匹配原始字符串是否能匹配的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* @description: str为原始字符串,regex为带*的比较字符串
* @param: [str, regex]
* @return: 匹配结果为true,不匹配结果为false
* @date: 2022/10/18
*/
private boolean compStarString(String str, String regex) {
// *号匹配
int strLength = str.length();
int regLength = regex.length();
int x1 = regex.indexOf("*");
switch (x1) {
case -1: {
//x1=-1 regex 中没有 * 号,不需要跌归计算
if (strLength == regLength) {
if (strLength == 0) return true;
for (int kk = 0; kk < regLength; kk++)//检测字符串是否匹配
if (str.charAt(kk) != regex.charAt(kk)) return false;
return true;
} else
return false;
}
case 0: {//x1=0 regex 中 * 号在首位
if (regLength == 1) return true;//只有一个星号,自然是匹配的,如 regex="*"
boolean right = false;
int p = 0;
// *号在首位,定位 * 号 后一位
for (int k = 0; k < strLength; k++)
if (str.charAt(k) == regex.charAt(x1 + 1) || regex.charAt(x1 + 1) == '*') {
p = k;
right = true;
break;
}//遇到 * 就直接 right=true;
if (right == false) return false;
else {
if (p == strLength) return true;
return compStarString(str.substring(p, strLength), regex.substring(x1 + 1, regLength));
}
}
default: { //x1>0
for (int i = 0; i < x1; i++)
if (str.charAt(i) != regex.charAt(i)) return false;
return compStarString(str.substring(x1, strLength), regex.substring(x1, regLength));
}
}
}

单元测试类

1
2
3
4
5
6
7
8
9
@Test
public void strTest(){
System.out.println("str=ABCD regex=*B*D :"+compStarString("ABCD","*B*D"));
System.out.println("str=ABCD regex=*BCD :"+compStarString("ABCD","*BCD"));
System.out.println("str=ABCD regex=*CD :"+compStarString("ABCD","*CD"));
System.out.println("str=ABCD regex=*A*B*D :"+compStarString("ABCD","*A*B*C*"));
System.out.println(compStarString("ABCD","**A**B*CD"));
}

运行结果如图:

判断字符串是否为整型和浮点型

1
2
3
4
5
6
7
8
9
10
/**
* @description: 判断字符串是否为整型和浮点型
* @param: [str]
* @return: boolean
* @date: 2022/10/19
*/
private boolean isNumeric(String str){
Pattern pattern = Pattern.compile("-?[0-9]+\\.?[0-9]*");
return pattern.matcher(str).matches();
}

String.getBytes()方法的解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
static byte[] encode(char[] ca, int off, int len) {
//该方法中主要通过该方法获取字符集名称
String csn = Charset.defaultCharset().name();
try {
// use charset name encode() variant which provides caching.
return encode(csn, ca, off, len);
} catch (UnsupportedEncodingException x) {
warnUnsupportedCharset(csn);
}
try {
return encode("ISO-8859-1", ca, off, len);
} catch (UnsupportedEncodingException x) {
// If this code is hit during VM initialization, MessageUtils is
// the only way we will be able to get any kind of error message.
MessageUtils.err("ISO-8859-1 charset not available: "
+ x.toString());
// If we can not find ISO-8859-1 (a required encoding) then things
// are seriously wrong with the installation.
System.exit(1);
return null;
}
}

/**
* Returns the default charset of this Java virtual machine.
* 返回此 Java 虚拟机的默认字符集。
* <p> The default charset is determined during virtual-machine startup and
* typically depends upon the locale and charset of the underlying
* operating system.
* 默认字符集在虚拟机启动期间确定,通常取决于底层操作系统的区域设置和字符集。
* @return A charset object for the default charset
*
* @since 1.5
*/
public static Charset defaultCharset() {
if (defaultCharset == null) {
synchronized (Charset.class) {
String csn = AccessController.doPrivileged(
new GetPropertyAction("file.encoding"));
Charset cs = lookup(csn);
if (cs != null)
defaultCharset = cs;
else
defaultCharset = forName("UTF-8");
}
}
return defaultCharset;
}

mac操作系统

说明: 查看上面的defaultCharset()方法的注视,说明是JVM启动的时候加载确定的,取决于操作系统的字符集.

本地测试验证: 再本地终端窗口,输入locale命令查看操作系统的编码集,如图为UTF-8

使用单元测试类,debug查看defaultCharset的属性值,也为UTF-8,如图:

测试发现idea的开发工具,如果VM里面不指定-Dfile.encoding参数,是根据项目的编码环境来的,如图:

运行测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.jvmproject.demo03;

import sun.security.action.GetPropertyAction;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.security.AccessController;

public class DefaultCharsetTest {
public static void main(String[] args) {
System.out.println(Charset.defaultCharset().name());
// System.out.println(System.getProperty("file.encoding"));
// System.out.println("a".getBytes());

}
}

结果如下:

调整idea的setting,再次运行,结果就为gbk了,如图:

也可以再mac 终端进行验证,再.zprofile文件里面设置export LC_ALL=zh_CN.GBK调整为gbk字符集环境,使用locale可以查看

设置调整前:

设置字符集:

设置调整后,如图:

调整前,在终端运行的效果如图:

调整完成后,在终端运行的效果如图:

但发现mac jdk11和jdk17版本

不管怎么设置都是UTF-8的编码集

window和linux环境

然后在linux环境测试了下发现jdk11和jdk17都是根据操作系统的编码集变化对应变化的,如图:

在windows环境查看操作系统编码集的方法,在dos终端输入chcp指定查看,然后通过对照code码查看

然后在控制面板里面,依次点击控制面板 -> 时钟和区域 -> 区域,弹出区域对话框。在管理选项卡中找到非 Unicode 程序的语言,点击更改系统区域设置,勾选Beta 版:使用 Unicode UTF-8 提供全球语言支持(U).如下图,点击确定需要重启.

重启之后再在dos里面输入chcp命令,就变成了utf-8的活动页代码了,如下图:

windows活动页码值和字符集对照关系见《字符集所占java字节数整理》文章

windows修改cmd.exe窗口的编码集:

1、win+r 打开运行窗口

2、输入regedit打开注册表编辑器

3、定位到HKEY_CURRENT_USER\Console%SystemRoot%_system32_cmd.exe

4、修改其中Codepage选项,勾选十进制,windows默认是936

437(英语)

65001(utf-8)

936(GBK)

参考文档:

https://blog.csdn.net/stone_bk/article/details/120798340