字符串String类

一:String类的概述

1.public final class String:发现String类被final修饰,说明不可以被继承。
2.implements java.io.Serializable, Comparable:

  • 实现了Serializable接口,支持序列化机制。
  • 实现了Comparable接口,可以比较大小。

3.private final char value[]:String类内部使用了字符数组进行存储数据,并且是常量(final修饰)。(基于JDK8,JDK9底层改为了byte[]数组)

二:String类的不可变 性

题外话:正确断句,可不能是不可 变性。
String对象一旦创建完毕,它的字符内容是不可以修改的。

1.当给字符串重新赋值时,需要重新开辟一块内存区域,不会改变原有区域的内容。

	@Test
    public void test1(){
        // 1.通过字面量的方式给字符串进行赋值操作
        String s1 = "abc";
        String s2 = "abc";

        // 2.证明不可变 性。
        System.out.println(s1 == s2);   // 对于引用数据类型,比较的是地址值。    运行结果为true
        s1 = "hello";
        System.out.println(s1);     // hello
    }

字符串不可变性1


2.当对现有的字符串进行拼接时,也需要重新开辟一块内存区域,不会改变原有区域的内容。

 @Test
    public void test2(){
        // 1.通过字面量的方式给字符串进行赋值操作
        String s1 = "abc";
        String s2 = "abc";

        // 2.证明不可变 性。
        s1 += "def";
        System.out.println(s1);     // abcdef
        System.out.println(s2);     // abc
    }

字符串不可变性2


3.当调用字符串的replace()方法修改字符或者字符串时,也需要重新开辟一块内存区域,不会改变原有区域的内容。

@Test
    public void test3(){
        // 1.通过字面量的方式给字符串进行赋值操作
        String s1 = "abc";
        String s2 = "abc";

        // 2.证明不可变 性。
        String str = s1.replace("a", "n");
        System.out.println(str);        // nbc
        System.out.println(s2);         // abc
    }

字符串不可变性3


总结:通过字面量的方式给字符串进行赋值操作,此时字符串的内容存储到了字符串常量池当中。并且字符串常量池是不会存储相同内容的字符串。

三:String类的实例化

String对象的创建

1.分析字面量创建字符串对象的方式和new + 构造器创建字符串对象的方式在内存中是如何存储数据的。
 @Test
    public void test4(){
        // 1.通过字面量的方式给字符串进行赋值操作
        String s1 = "JAVAEE";
        String s2 = "JAVAEE";

        // 2.通过new + 构造器的方式创建字符串对象
        // 面试题:String s3 = new String("JAVAEE")方式创建对象,在内存中创建了几个对象?
        // 两个:一个是堆空间中的new结构,另一个是char[]对应的常量池中的数据"JAVAEE";
        String s3 = new String("JAVAEE");
        String s4 = new String("JAVAEE");

        // 3.测试结果
        System.out.println(s1 == s2);   // true
        System.out.println(s1 == s3);   // false
        System.out.println(s1 == s4);   // false
        System.out.println(s3 == s4);   // false

    }

字符串实例化方式


2.字符串对象是如何存储的?
package cn.xuguowen.java;

/**
 * @author xuguowen
 * @create 2021-02-22 17:11
 * @Description     字符串对象是如何存储的?
 */
public class PersonTest {
    public static void main(String[] args) {
        // 创建两个Person对象
        Person p1 = new Person("Tom", 18);
        Person p2 = new Person("Tom", 18);

        // 测试结果
        System.out.println(p1 == p2);       // false
        // 首先要明白采取的是字面量的方式为字符串name进行赋值的.两个对象的name属性都存储的是常量池中内容是Tom的地址
        System.out.println(p1.name == p2.name);     // true
        // 由于String类重写了equals()方法,内容相同返回true
        System.out.println(p1.name.equals(p2.name));    // true
        System.out.println(p1.name == "Tom");           // true

        p1.name = "Andy";
        // 又一次体现了字符串的不可变 性
        System.out.println(p2.name);        // Tom

    }
}

class Person{
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }
}

字符串对象的存储


3.小试牛刀
 @Test
    public void test6(){
        String s1 = "javaEE";
        String s2 = "hadoop";

        String s3 = "javaEEhadoop";
        String s4 = "javaEE" + "hadoop";
        String s5 = s1 + "hadoop";
        String s6 = "javaEE" + s2;
        String s7 = s1 + s2;

        // 先明白使用字面量的方式创建字符串对象,其内容存储到字符串常量池中,并且字符串常量池中不会存储相同内容的字符串
        System.out.println(s3 == s4);       // true
        System.out.println(s3 == s5);       // false
        System.out.println(s3 == s6);       // false
        System.out.println(s3 == s7);       // false
    }

结论:

  • 常量与常量的拼接结果在字符串常量池中,并且常量池中不会存在相同内容的常量。
  • 只要其中有一个变量,结果就在堆中。
  • 小试牛刀
4.intern()方法的使用
  • A.intern():方法的作用:
    1.如果字符串常量池中存在与A内容相同的字符串对象C时,就返回C。
    2.否则,将A字符串对象的内容加入到字符串常量池当中,返回A。
 /*
        A.intern():方法的作用:
	        1.如果字符串常量池中存在与A内容相同的字符串对象C时,就返回C。
	        2.否则,将A字符串对象的内容加入到字符串常量池当中,返回A。
     */
    @Test
    public void test7(){
        int a = 4, b = 5, c = 6;
        String s6 = String.format("%d%d%d",a,b,c);
        String s7 = String.format("%d%d%d",a,b,c);
        // 调用intern()方法,先去scp查找,此时scp没有,所以将s6字符串对象放入常量池中(类似于剪切,此时不是拷贝副本)
        String s8 = s6.intern();
        String s9 = s7.intern();
        String s10 = "456";
        System.out.println(s6 == s7);       // false
        System.out.println(s6 == s8);		// true
        System.out.println(s6 == s9);		// true
        System.out.println(s6 == s10);		// true
    }
5.面试题
/**
 * @author xuguowen
 * @create 2021-02-23 13:21
 * @Description     字符串的一道面试题
 */
public class StringTest {

    String str = new String("good");
    char[] ch = {'t','e','s','t'};

    public void change(String str,char[] ch){
        str = "test ok";
        ch[0] = 'b';
    }
    public static void main(String[] args) {
        StringTest st = new StringTest();
        st.change(st.str,st.ch);

        System.out.println(st.str);     // good
        System.out.println(st.ch);      // best

    }
}

面试题


四:String类的常用方法

1.int length() 返回此字符串的长度。

@Test
    public void test1(){
        // int length()返回此字符串的长度。
        String str = "HelloWorld";
        System.out.println("字符串的长度为:" + str.length());
    }

2.char charAt(int index) 返回指定索引处的字符。

 @Test
    public void test2(){
        // char charAt(int index)  返回指定索引处的字符
        String str = "HelloWorld";
        char ch = str.charAt(0);
        System.out.println(ch);     // H
    }

3.boolean isEmpty() 判断是否是空字符串。

 @Test
    public void test3(){
        // boolean isEmpty()   判断是否是空字符串
        String str = "HelloWorld";
        System.out.println(str.isEmpty());      // false
        String str1 = "";
        System.out.println(str1.isEmpty());     // true
    }

4.String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写。
String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写。

 @Test
    public void test4(){
        /*
                String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
                String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
         */
        String str = "HelloWorld";
        String str1 = str.toLowerCase();
        System.out.println(str);        // 体现了字符串的不可变 性
        System.out.println(str1);
    }

5.String trim():返回字符串的副本,忽略前导空白和尾部空白。

 @Test
    public void test5(){
        // String trim():返回字符串的副本,忽略前导空白和尾部空白。
        String str = "   he  llo   world    ";
        String str1 = str.trim();
        System.out.println(str);        // 体现了字符串的不可变 性
        System.out.println(str1);

    }

6.boolean equals(Object obj):比较字符串的内容是否相同。
boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写。

@Test
    public void test6() {
       /*
                boolean equals(Object obj):比较字符串的内容是否相同。
                boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写。
        */
        String str1 = "Hello";
        String str2 = "hello";
        System.out.println(str1.equals(str2));      // false
        System.out.println(str1.equalsIgnoreCase(str2));        // true

    }

7.String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”。

 @Test
    public void test7() {
        // String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”。
        String str1 = "hello";
        String str2 = str1.concat("world");
        System.out.println(str1);       // hello,体现了字符串的不可变 性
        System.out.println(str2);       // helloworld

    }

8.int compareTo(String anotherString):比较两个字符串的大小。
int compareTo(String str):比较两个字符串的大小(忽略大小写)。

@Test
    public void test8() {
        // int compareTo(String anotherString):比较两个字符串的大小。每个字符逐一比较,根据ASCII码比较
        String s1 = "abc";
        String s2 = "abe";
        System.out.println(s1.compareTo(s2));   // -2 负数说明调用者小于参数

        String s3 = "abc";
        String s4 = "abc";
        System.out.println(s3.compareTo(s4));   // 0 说明相等

        String s5 = "abc";
        String s6 = "ABC";
        System.out.println(s5.compareTo(s6));   // 32 正数说明调用者大于参数

        // int compareTo(String str):比较两个字符串的大小(忽略大小写)。
        String s7 = "abc";
        String s8 = "ABC";
        System.out.println(s7.compareToIgnoreCase(s8));

    }

9.String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。

 @Test
    public void test9() {
       /*
        String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
        String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。

        */
        String str1 = "HelloWorld";
        System.out.println(str1.substring(0));      // HelloWorld
        System.out.println(str1.substring(5));      // World

        String str2 = str1.substring(0, 5);     // Hello,含头不含尾
        System.out.println(str2);
        System.out.println(str1);                   // HelloWorld
    }

10.boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束。
boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始。
boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始。

 @Test
    public void test10() {
        /*

        boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
        boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
        boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始

         */

        String str1 = "helloworld";
        boolean ld = str1.endsWith("ld");
        System.out.println(ld);     // true
        boolean dl = str1.endsWith("dl");
        System.out.println(dl);     // false

        boolean he = str1.startsWith("he");
        System.out.println(he);     // true
        boolean eh = str1.startsWith("eh");
        System.out.println(eh);     // false

        boolean el = str1.startsWith("el", 1);
        System.out.println(el);     // true
        boolean le = str1.startsWith("le", 1);
        System.out.println(le);     // false
    }

11.boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true。
int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引。
int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引。
int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
注:indexOf和lastIndexOf方法如果未找到都是返回-1

 @Test
    public void test11() {
        /*

boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true。
int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引。
int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引。
int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。
**注:indexOf和lastIndexOf方法如果未找到都是返回-1**
*
         */
        String str1 = "helloworld";
        boolean he = str1.contains("he");
        System.out.println(he);     // true
        boolean eh = str1.contains("eh");
        System.out.println(eh);     // false

        String str2 = "helloworlld";
        int ow = str2.indexOf("ow");
        System.out.println(ow);     // 4

        int l = str2.indexOf("ll", 4);
        System.out.println(l);      // 8

        int ll = str2.lastIndexOf("ll");
        System.out.println(ll);     // 8

        int ll1 = str2.lastIndexOf("ll", 7);
        System.out.println(ll1);    // 2


    }

12.String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
String replaceAll(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
String replaceFirst(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

 @Test
    public void test12(){
        /*
String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
String replaceAll(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
String replaceFirst(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
         */
        String str1 = "家里蹲蹲学java";
        String str2 = str1.replace("蹲", "站");
        System.out.println(str1);       // 家里蹲蹲学java
        System.out.println(str2);       // 家里站站学java

        String str3 = str1.replace("java", "hadoop");
        System.out.println(str3);       // 家里蹲蹲学hadoop

        System.out.println("********************************");
        String str = "12hello34world5java7891mysql456";
        //把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉
        String string = str.replaceAll("\\d+", ",");
        String string1 = string.replaceAll("^,|,$", "");
        System.out.println(string1);     // hello,world,java,mysql

    }

13.boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。

  @Test
    public void test14(){
        /*
boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
         */

        String str = "12345";
        //判断str字符串中是否全部有数字组成,即有1-n个数字组成
        boolean matches = str.matches("\\d+");
        System.out.println(matches);        // true
        String tel = "0352-4534289";
        //判断这是否是一个大同的固定电话
        boolean result = tel.matches("0571-\\d{7,8}");
        System.out.println(result);         // false

        System.out.println("********************************");

        String str1 = "hadoop|web|java";
        String[] strs = str1.split("\\|");
        for (int i = 0; i < strs.length; i++) {
            System.out.println(strs[i]);
        }
        System.out.println();
        String str2 = "hadoop.web.java";
        String[] strs2 = str2.split("\\.");
        for (int i = 0; i < strs2.length; i++) {
            System.out.println(strs2[i]);
        }
    }

五:String与基本数据类型包装类之间的转换

import org.junit.Test;

/**
 * @author xuguowen
 * @create 2021-02-25 12:52
 * @Description     String 与基本数据类型,包装类之间的转换
 *                  1.String --> 基本数据类型、包装类:parseXxx()方法
 *                  2.基本数据类型、包装类 --> String:
 *                         ①:调用valueOf()
 *                         ②:使用 + 拼接
 */
public class StringTest2 {

    @Test
    public void test1(){
        String str = "123";
        int num = Integer.parseInt(str);

    }

    @Test
    public void test2(){
        int num = 123;
        // 方式一
        String str1 = String.valueOf(num);
        // 方式二
        String str2 = num + "";

    }
}

六:String与char[]数组之间的转换

/*
            char[] 与 String之间的转换
     */
    @Test
    public void test4(){
        char[] chars = new char[]{'h','e','l','l','o'};
        // 调用String(char[] ch)
        String str = new String(chars);

    }
    /*
            String 与 char[]数组之间的转换
                调用String类中的toCharArray()方法

     */

    @Test
    public void test3(){
        String str = "123abc";
        char[] chars = str.toCharArray();

        // 遍历数组,输出元素
        for (int i = 0; i < chars.length; i++) {
            System.out.println(chars[i]);
        }
    }

七:String与byte[]数组之间的转换

/*
            String与byte[]数组之间的转换
                1.String --> byte[]:getByte()方法(编码)
                2.byte[] --> String:String(byte[] by)构造器 (解码)

            编码:String --> 字节(泛泛的将:看的懂得 --> 看不懂得二进制数据)
            解码:字节 --> String(看不懂得二进制数据 --> 看的懂得)

            说明:解码时,要求使用的字符集必须和编码时使用的字符集一致。否则出现乱码!
     */
    @Test
    public void test5() throws UnsupportedEncodingException {
        String str = "123abc中国";
        byte[] bytes = str.getBytes();  // 使用默认的字符集进行编码
        System.out.println(Arrays.toString(bytes));

        byte[] gbks = str.getBytes("gbk");  // 使用gbk字符集进行编码
        System.out.println(Arrays.toString(gbks));

        System.out.println("**********解码************");
        String str1 = new String(bytes);    // 解码
        System.out.println(str1);

        String str2 = new String(gbks);
        System.out.println(str2);   // 出现乱码,因为编码集和解码集不一致

        String str3 = new String(gbks, "gbk");
        System.out.println(str3);

    }

八:String、StringBuffer、StringBuilder的异同

  • 相同点:底层都采用char[]数组进行存储数据
  • 不同点:
    1.String不可变的字符序列。
    2.StringBuffer可变的字符序列,线程安全,效率低。
    3.StringBuilder可变的字符序列,线程不安全,效率高。

九:StringBuffer、StringBuilder的常用方法

package cn.xuguowen.java;

import org.junit.Test;

/**
 * @author xuguowen
 * @create 2021-02-26 14:48
 * @Description String、StringBuffer、StringBuilder三者之间的异同?
 * 相同点:底层都是采用char[]数组进行存储
 * 不同点:
 * 1.String:不可变的字符序列
 * 2.StringBuffer:可变的字符序列,线程安全的,效率低
 * 3.StringBuilder:可变的字符序列,线程不安全的,效率高
 * <p>
 * 源码分析:
 * String str = new String(); // char[] value = new char[0];
 * String str1 = new String("abc");// char[] value = new char[]{'a','b',''c};
 * <p>
 * StringBuffer sb = new StringBuffer();// char[] value = new char[16];
 * StringBuffer sb1 = new StringBuffer("abc");// char[] value = new char["abc".length + 16]
 * <p>
 * 问题:底层涉及到数组的扩容,扩容为原来的2倍 + 2,同时将原有数组中的元素复制到新数组当中
 */
public class StringBufferBuilderTest {
    /*
StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
StringBuffer delete(int start,int end):删除指定位置的内容
StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
StringBuffer insert(int offset, xxx):在指定位置插入xxx
StringBuffer reverse() :把当前字符序列逆转
public int indexOf(String str)
public String substring(int start,int end)
public int length()
public char charAt(int n )
public void setCharAt(int n ,char ch)
     */
    @Test
    public void test() {
        StringBuffer sb = new StringBuffer("abc");
        sb.append(1);
        sb.append("2");
        System.out.println(sb); // abc12

//        sb.delete(3,5);
//        System.out.println(sb); // abc
//
//        sb.replace(3,5,"de");
//        System.out.println(sb);     // abcde

        sb.insert(3, "de");
        System.out.println(sb);     // abcde12

//        sb.reverse();
//        System.out.println(sb);     // 21edcba

        String str = sb.substring(5, 7);
        System.out.println(str);    // 12
	}
}

十:面试题

 @Test
    public void test2(){
        String str = null;
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        System.out.println(sb.length());//
        System.out.println(sb);//
        StringBuffer sb1 = new StringBuffer(str);
        System.out.println(sb1);//
    }

在这里插入图片描述


@Test
    public void test3(){
        String a = "123";
        String b = "123";

        String c = new String("123");
        String d = new String("123");

        System.out.println(a.equals(b));        // true
        System.out.println(a == b);             // true

        System.out.println(c.equals(d));        // true
        System.out.println(c == d);             // false

        System.out.println(a.equals(c));        // true
        System.out.println(a == c);             // false
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值