字符串 String

  • 一、概述
  • 定义
  • 二、Latin1 与 UTF-16
  • Latin1
  • StringLatin1类 (byte[] → char[]) 数组转换方法——inflate
  • UTF-16
  • StringUTF16类 (byte[] → char[]) 数组转换方法——getChars
  • 三、相关方法
  • 1、equals
  • equals(Object anObject)、创建字符串的相关事项
  • 2、equalsIgnoreCase
  • equalsIgnoreCase(String anotherString)
  • 3、compareTo
  • compareTo(String anotherString)
  • 4、compareToIgnoreCase
  • compareToIgnoreCase(String str)
  • 5、toCharArray
  • toCharArray()
  • 6、charAt
  • 7、toUpperCase / toLowerCase
  • ① toUpperCase()
  • ② toLowerCase()
  • 8、trim
  • trim()
  • 9、indexOf / lastIndexOf
  • ① indexOf(String str) / indexOf(int ch)
  • ② indexOf(String str, int fromIndex) / indexOf(int ch, int fromIndex)
  • ③ lastIndexOf(String str) / lastIndexOf(int ch)
  • ④ lastIndexOf(String str, int fromIndex) / lastIndexOf(int ch, int fromIndex)
  • 10、substring
  • ① substring(int beginIndex, int endIndex)
  • ② substring(int beginIndex)
  • 11、concat
  • concat(String str)
  • 12、replace
  • replace(char oldChar, char newChar)
  • 13、valueOf
  • valueOf(int i / char c / long l / float f / double b / boolean / char[] data)
  • 14、contains
  • contains(CharSequence s)
  • 15、join
  • join(CharSequence delimiter, Char[] chs)
  • 16、length
  • length()
  • 17、isEmpty
  • isEmpty()
  • 18、split
  • 19、startsWith / endsWith
  • 四、练习
  • Ⅰ:将一个字符串进行反转,例如:“abcd” → “dcba”。
  • Ⅱ:判定输入的一个字符串是否全为数字,使用两种方式完成。
  • ①普通方法
  • ②正则表达式
  • Ⅲ:输入一个由小写字符组成的字符串,统计出每个字符出现的次数
  • Ⅳ:去除标签字符串



目标:熟悉字符串的相关方法,并掌握其用法。

一、概述

定义

字符串或串(String)是由数字、字母、下划线组成的一串字符。

  • jdk1.8及以前String使用的是char数组,jdk1.9及以后使用的是byte数组。

核心源码:

① jdk8:

java 定义string需要先设置为空吗 java中string的定义_System


② jdk9:

java 定义string需要先设置为空吗 java中string的定义_字符串_02

  • 通过查看源码,我们可以得知,String字符串的本质是数组。
  • 我们以jdk15为例,进行介绍。

二、Latin1 与 UTF-16

  • 与String类底层相关的两种编码方式,分别为Latin1和UTF-16,它们分别代表两个特殊类:StringLatin1StringUTF16,负责处理不同编码的字符串,提供不同的方法。我们在使用字符串相关方法时,会先在String类内进行判断,决定使用哪个类所提供的相应方法,然后进入相应方法,经过逐次返回,最终将结果返回给我们。

Latin1

  • Latin1ISO-8859-1的别名,有些环境下写作Latin-1。
  • ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致。
  • 0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。

StringLatin1类 (byte[] → char[]) 数组转换方法——inflate

java 定义string需要先设置为空吗 java中string的定义_java_03

  • 该方法将byte[]转化为char[]。
  • 对每个元素(字节)进行取低8位操作,转化为字符后,依次赋值,并整合为字符数组。

UTF-16

  • UTF-16Unicode字符编码五层次模型的第三层字符编码表(Character Encoding Form,也称为
    “storage format”)的一种实现方式。
  • 即把Unicode字符集的抽象码位映射为16位长的整数(即码元)的序列,用于数据存储或传递。
  • Unicode字符的码位,需要1个或者2个16位长的码元来表示,因此这是一个变长表示。

StringUTF16类 (byte[] → char[]) 数组转换方法——getChars

java 定义string需要先设置为空吗 java中string的定义_字符串_04

  • 该方法依次调用取字符方法getChar,同样可以将byte[]转化为char[]。

三、相关方法

1、equals

  • equals方法用于将字符串与指定的对象比较,String 类中重写了 equals方法用于比较两个字符串的内容是否相等。
  • equals的用法如下:
  • java 定义string需要先设置为空吗 java中string的定义_System_05

equals(Object anObject)、创建字符串的相关事项

① 不使用 new 关键字创建字符串:

String str = "abc";
String str2 = "abc";
System.out.println(str==str2);
System.out.println(str.equals(str2));

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_字符串_06

② 使用 new 关键字创建字符串:

String str3 = new String("abc");
String str4 = new String("abc");
System.out.println(str3==str4);
System.out.println(str3.equals(str4));

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_字符串_07

使用 == 和 equals() 比较字符串。
String 中 == 比较引用地址是否相同,equals() 比较字符串的内容是否相同:

String s1 = "Hello";              // String 直接创建
String s2 = "Hello";              // String 直接创建
String s3 = s1;                   // 相同引用
String s4 = new String("Hello");  // String 对象创建
String s5 = new String("Hello");  // String 对象创建
 
s1 == s1;         // true, 相同引用
s1 == s2;         // true, s1 和 s2 都在公共池中,引用相同
s1 == s3;         // true, s3 与 s1 引用相同
s1 == s4;         // false, 不同引用地址
s4 == s5;         // false, 堆中不同引用地址
 
s1.equals(s3);    // true, 相同内容
s1.equals(s4);    // true, 相同内容
s4.equals(s5);    // true, 相同内容

java 定义string需要先设置为空吗 java中string的定义_字符串_08

编译阶段:
① 常量池中的每一项常量都是一个表,都有自己对应的类型。
② String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值。该表只存储文字字符串值,不存储符号引用。
③ JVM的常量池最多可放65535个项。第0项不用。最后一项最多只能是65534(下标值)。而每一项中,若是放一个UTF-8的常量串,其长度最长是:65535个字节(不是字符)。

运行时阶段:
① String内部是以char数组的形式存储,数组的长度是int类型,String允许的最大长度就是Integer.MAX_VALUE,即2147483647。
② 由于java中的字符是以16位存储的,因此大概需要4GB的内存才能存储最大长度的字符串。

  • equals源码如下所示:

2、equalsIgnoreCase

  • equalsIgnoreCase方法将字符串与指定的字符串比较,并且忽略大小写。

equalsIgnoreCase(String anotherString)

String str1 = "I love you";
String str2 = "I LOVE YOU";
System.out.println("比较字符串是否相等, 并忽略字母大小写:" + str1.equalsIgnoreCase(str2));

运行结果如下所示:

java 定义string需要先设置为空吗 java中string的定义_System_09

3、compareTo

  • compareTo 方法用于将 Number 对象与方法的参数字符串进行比较,并返回目标字符串与源字符串,字符值间隔值(差值)之和。
  • compareTo 的用法如下:

compareTo(String anotherString)

String str = "I love you";
System.out.println(str.compareTo("I love u"));
System.out.println(str.compareTo("I love you"));
System.out.println(str.compareTo("I love you, haha!"));
System.out.println(str.compareTo("123"));
System.out.println(str.compareTo("sasdhasf5433^%"));

运行结果如下所示:

java 定义string需要先设置为空吗 java中string的定义_字符串_10

4、compareToIgnoreCase

  • compareToIgnoreCase 方法与compareTo 方法类似,唯一的区别是,该方法忽略大小写。
  • compareToIgnoreCase 的用法如下:

java 定义string需要先设置为空吗 java中string的定义_字符串_11

compareToIgnoreCase(String str)

String str1 = "I love you 123";
String str2 = "I LOVE YOU 123";
String str3 = "I LOVE YOU 124";
System.out.println(str1.compareToIgnoreCase(str2));
System.out.println(str1.compareToIgnoreCase(str3));

java 定义string需要先设置为空吗 java中string的定义_System_12

5、toCharArray

  • toCharArray 方法将字符串转为字符数组
  • toCharArray 的用法如下:

toCharArray()

String str = "I love you";					//定义字符串
char[] chs = str.toCharArray();				//使用该方法,将字符串转化为字符串
System.out.println(Arrays.toString(chs));	//使用Arrays数组辅助类,转化为保留数组格式的字符串,并打印输出

代码运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_java_13

  • toCharArray 源码如下所示:
  • 可以根据字符集的不同,调用不同类的toChars方法,从而将字符串转化为字符数组

6、charAt

  • charAt 方法取出字符串中的某个字符
  • charAt 的用法如下:

7、toUpperCase / toLowerCase

① toUpperCase()

  • toUpperCase 方法将字符串中所有小写字母转换为大写字母
  • toUpperCase 的用法如下:
String str = "abcdefg";
System.out.println("处理前的字符串:"+str);
str = str.toUpperCase();
System.out.println("处理后的字符串:"+str);

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_正则表达式_14

② toLowerCase()

  • toLowerCase方法将字符串中所有大写字母转换为小写字母
  • toLowerCase的用法如下:

java 定义string需要先设置为空吗 java中string的定义_bc_15

String str = "AAAAA";
System.out.println("处理前的字符串:"+str);
str = str.toLowerCase();
System.out.println("处理后的字符串:"+str);

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_java_16

  • 这里,我们对它们的源码,暂不做深入探讨。

8、trim

trim()

  • trim方法用于修剪字符串,去除字符串首尾空白字符,并返回处理后的字符串。
  • trim的用法如下:
String str = "    \n  \t  \r    abcdefg      QWERTYU      23333";
System.out.println("处理前的字符串:"+str);
str = str.trim();
System.out.println("处理后的字符串:"+str);

以上代码运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_java_17

  • trim源码如下所示:
  • java 定义string需要先设置为空吗 java中string的定义_System_18

  • 首先,String类本身的trim()方法,会使用isLatin1()方法对字符集进行判断,这里用到了三目运算符。
  • 当字符集为Latin1时,将字符串的值作为参数传递并调用StringLatin1类的trim()方法,同样若条件不满足(当字符集为UTF16时),则调用StringUTF16类的trim()方法。
  • StringLatin1类的trim()方法:
  • java 定义string需要先设置为空吗 java中string的定义_字符串_19

  • StringUTF16类的trim()方法:
  • java 定义string需要先设置为空吗 java中string的定义_正则表达式_20

  • 两种字符集的trim方法思想基本一致,首先定义“串首索引值st”、“串尾索引值len”。
  • 第一个循环从串首向后搜索,直到找到了字节码大于空格值的字符位置(空格是最大的 “空位值”),否则将使得串首索引值st不断增加(后移)。
  • 第二个循环从串尾向前搜索,同理,否则将使得串尾索引值st不断减少(前移)。
  • 一旦完成两次循环,视为完成寻找。根据索引,重构字符串,并返回结果值
  • 【注】:这是一张Unicode字符列表,可以看到:空格是最大的 “空位值”。

java 定义string需要先设置为空吗 java中string的定义_字符串_21

9、indexOf / lastIndexOf

  • indexOf / lastIndexOf 方法主要用于寻找第一次 / 最后一次 出现某字符 / 字符串的位置索引,并返回相应索引值;若没有找到,则返回-1。
  • indexOf 从串首向串尾搜索,而lastIndexOf从串尾向串首搜索。

    我们本例使用字符串如下:
String str = "abcdefg a13231";

① indexOf(String str) / indexOf(int ch)

  • 这种寻找方式,默认开始搜寻位置为串首。
String str = "abcdefg a13231";
System.out.println("第一次出现字符'a'的索引(下标):"+str.indexOf('a'));
System.out.println("第一次出现字符串'efg'的索引(下标):"+str.indexOf("efg"));

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_bc_22

② indexOf(String str, int fromIndex) / indexOf(int ch, int fromIndex)

  • 这种寻找方式,可以任意指定开始搜寻位置。
String str = "abcdefg a13231";
System.out.println("第一次出现字符'a'的索引(下标),指定从3开始向后进行搜索:"+str.indexOf('a',3));
System.out.println("第一次出现字符串'efg'的索引(下标),指定从6开始向后进行搜索:"+str.indexOf("efg",6));

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_System_23

③ lastIndexOf(String str) / lastIndexOf(int ch)

  • 这种寻找方式默认开始位置为串尾。
String str = "abcdefg a13231";
System.out.println("最后一次出现字符'a'的索引(下标):"+str.lastIndexOf('a'));
System.out.println("最后一次出现字符串'efg'的索引(下标):"+str.lastIndexOf("efg"));

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_bc_24

④ lastIndexOf(String str, int fromIndex) / lastIndexOf(int ch, int fromIndex)

  • 这种寻找方式,可以任意指定开始搜寻位置。
String str = "abcdefg a13231";
System.out.println("最后一次出现字符'a'的索引(下标),指定从3开始向前进行搜索:"+str.lastIndexOf('a',3));
System.out.println("最后一次出现字符串'efg'的索引(下标),指定从3开始向前进行搜索:"+str.lastIndexOf("efg",6));

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_正则表达式_25

  • indexOf / lastIndexOf 的源码较为复杂,这里我们不做探讨, 仅了解其使用方法即可。

10、substring

  • substring方法用于截取字符串,根据输入的参数,截取字串并返回。
  • 可以看到,该方法有两个重载。
  • substring的用法如下:

① substring(int beginIndex, int endIndex)

  • substring 的这种重载,用于截取字符串,索引间的子串。
  • 第一个参数为起始处索引,第二个参数为结束处索引。
String str = "我很开心!";
System.out.println("处理前的字符串:"+str);
str = str.substring(1,4);
System.out.println("处理后的字符串:"+str);

以上代码运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_bc_26

  • substring方法的这种重载的源码如下所示:
  • java 定义string需要先设置为空吗 java中string的定义_System_27

  • 首先,定义length记录字符串长度。
  • 其次,使用checkBoundsBeginEnd方法检查传入参数是否满足范围要求。
  • 而后,使用if进行判断,如果字串等于字符串本身,则不做截取,直接返回该字符串。
  • 若不满足if,则记录应写个长度,并根据字符集,调用相关字符集串类中的newString方法重构字符串,并返回相应的结果值。

② substring(int beginIndex)

  • substring 这种重载,用于截取字符串,从传入索引值到字符串末尾的字串。
  • substring 的用法如下:
String str = "我很开心!";
System.out.println("处理前的字符串:"+str);
str = str.substring(2);
System.out.println("处理后的字符串:"+str);

以上代码运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_正则表达式_28

  • substring方法这种重载的源码如下所示:
  • 可以看到,该方法的底层帮我们调用了上一种方法,第一个参数为输入的起始值,第二个参数默认为字符串长度。

11、concat

  • concat 方法用于连接两个字符串,该方法对不修改原本的引用,而是生成新的字符串。
  • concat的用法如下:

concat(String str)

String str1 = "abc";
System.out.println(str1.concat("123"));
System.out.println(str1);

以上代码运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_java_29

  • concat的源码较为复杂,这里我们不做探讨, 仅了解其使用方法即可。

12、replace

  • replace用于将字符串中所有的一种字符,替换为另一种字符。
  • replace的用法如下:

replace(char oldChar, char newChar)

  • replace 用于 替换字符串中的所有某种字符。
String str = "abcdefaaag";
System.out.println("处理前的字符串:"+str);
str = str.replace('a','R');
System.out.println("处理后的字符串:"+str);

运行结果如下所示:

java 定义string需要先设置为空吗 java中string的定义_字符串_30

  • replace的源码较为复杂,这里我们不做探讨, 仅了解其使用方法即可。

13、valueOf

  • valueOf 方法将传入参数转为字符串
  • valueOf 可接受参数如下所示:

valueOf(int i / char c / long l / float f / double b / boolean / char[] data)

System.out.println(String.valueOf(1));
System.out.println(String.valueOf('a'));
System.out.println(String.valueOf(System.currentTimeMillis()));
System.out.println(String.valueOf(3189.756));
System.out.println(String.valueOf(true));
System.out.println(String.valueOf(new char[]{'p','e','a','r'}));

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_正则表达式_31

  • valueOf的源码较为复杂,这里我们不做探讨, 仅了解其使用方法即可。

14、contains

  • contains方法用于判断字符串中,是否包含子串。
  • contains的使用方法如下:

contains(CharSequence s)

String str = "abcdefaaag";
boolean flag = str.contains("asda");
System.out.println(flag);

运行结果如下所示:

java 定义string需要先设置为空吗 java中string的定义_java_32

String str = "abcdefaaag";
boolean flag = str.contains("aaa");
System.out.println(flag);

运行结果如下所示:

java 定义string需要先设置为空吗 java中string的定义_java_33

  • contains源码:

15、join

  • join 方法可将数组、集合以某拼接符拼接到一起形成新的字符串。

join(CharSequence delimiter, Char[] chs)

  • join 的使用方法如下:
String[] strs = {"A","b","d","3"};
String str = String.join(",",strs);
System.out.println(str);

运行结果如下所示:

java 定义string需要先设置为空吗 java中string的定义_字符串_34

16、length

  • length 方法用于获取字符串的长度,返回值类型为int。

length()

  • length 的使用方法如下:
String str = "abcdefaaag";
System.out.println("字符串str长度为:"+str.length());

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_bc_35

17、isEmpty

  • isEmpty 方法用于 检查字符串长度是否长度为0。

isEmpty()

//字符串长度为0
String str1 = "";
//引用指向null
String str2 = null;
//打印结果
System.out.println("字符串长度为0:" + str1.isEmpty());
System.out.println("引用指向null:" + str2.isEmpty());

运行结果如下:

java 定义string需要先设置为空吗 java中string的定义_bc_36

  • 可以看到当为null时,抛出了空指针异常(NullPointerException),这证明了引用指向null,并非指向一个字符串对象,null代表没有指向任何内存空间
  • isEmpty()源码:
  • java 定义string需要先设置为空吗 java中string的定义_bc_37

  • 可以看到它的源码,检查长度是否为0。

18、split

  • split 方法用于按模式分割字符串,将其转化为字符数组。

19、startsWith / endsWith

  • startsWith / endsWith 方法分别用于检测字符串是否以某串作为开头 / 结尾。
  • startsWith 方法检测串首是否匹配,endsWith 方法检测串尾是否匹配。

四、练习

Ⅰ:将一个字符串进行反转,例如:“abcd” → “dcba”。

public String reverseString(String str) {
   char[] chs = str.toCharArray();
   for (int i = 0; i < chs.length/2; i++) {
       chs[i] = (char) (s[i] ^ chs[chs.length-i-1]);
       chs[chs.length-i-1] = (char) (chs[i] ^ chs[chs.length-i-1]);
       chs[i] = (char) (s[i] ^ chs[chs.length-i-1]);
   }
   return String.valueOf(s);
}
String str = "abcdefg";
System.out.println("处理前的字符串:"+str);
System.out.println("处理前的字符串:"+ reverseString(str));

java 定义string需要先设置为空吗 java中string的定义_正则表达式_38

Ⅱ:判定输入的一个字符串是否全为数字,使用两种方式完成。

①普通方法

public boolean isNumStr(String str){
        char[] chs = str.toCharArray();
        if(str == null||str==""){
            return false;
        }
        for(int i =0 ;i < chs.length;i++){
            if(!(chs[i] > '0' && chs[i] < '9')){
                return false;
            }
        }
        return true;
    }

②正则表达式

public static boolean isNumStr(String str){
    if(str.matches("[0-9]+")){
        return true;
    }
    return false;
}

判断字符串:

String str = "abcdefg a13231";
String str2 = "13231";
System.out.println("是否为纯数字字符串:"+isNumStr(str));
System.out.println("是否为纯数字字符串:"+isNumStr(str2));

运行结果如下所示:

java 定义string需要先设置为空吗 java中string的定义_正则表达式_39

Ⅲ:输入一个由小写字符组成的字符串,统计出每个字符出现的次数

public void lowCaseLetterInString() {
	// 仅含有小写字母的字符串
	String str = "asnhfahfrlkanwdflkad";
	// 转换为字符数组
	char[] chs = str.toCharArray();
	// 计数用int数组
	int[] count = new int[26];
	// 计数
	for (int i = 0; i < chs.length; i++) {
		count[chs[i] - 'a'] += 1;
	}
	// 遍历
	int max = -1;
	int pos = 0;
	for (int j = 0; j < chs.length; j++) {
		if (count[j] > max) {
			max = count[j];
			System.out.println(max);
		}
		System.out.println((char) ('a' + j) + "出现的次数:" + count[j]);
	}
	System.out.println("出现频率最高的字母为:" + (char) ('a' + pos));
}

运行结果如下所示:

java 定义string需要先设置为空吗 java中string的定义_System_40

Ⅳ:去除标签字符串

java 定义string需要先设置为空吗 java中string的定义_java_41

public void grabInfo() {
	String str4 = "<h1>這是測試結果</h1><p>test a</p>";
	String pattern3 = "(<\\w+>)|(</\\w+>)";
	String str5 = str4.replaceAll(pattern3,"");
	System.out.println(str5);
}

运行结果如下所示:

java 定义string需要先设置为空吗 java中string的定义_bc_42