Java-String类

文章详细介绍了Java中String类的构造方法,包括通过常量、new操作以及字符数组创建字符串。接着讨论了字符串的比较,如使用==、equals()、compareTo()和compareToIgnoreCase()方法。此外,还涉及字符串的查找、转化、替换、拆分、截取和其他操作。文章强调了String的不可变性,推荐在需要修改字符串时使用StringBuilder或StringBuffer,并指出两者的线程安全差异。最后,提到了字符串常量池的概念和对象创建的影响。
摘要由CSDN通过智能技术生成

写在前面

字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。在开发和校招中, 字符串也是常客, 所以这一章节也非常重要, 在本章节中, 我们需要掌握的是:

  1. 认识String类
  2. 了解String类的基本用法
  3. 熟练掌握String的常见操作
  4. 认识字符串常量池
  5. 认识 StringBuffer 和 StringBuilder

1 String类的常用方法

1.1 字符串的构造

String 类提供的构造方法有很多, 我们首先掌握以下常见的三种:

  public static void main(String[] args) {
        // 使用常量串构造, 直接使用双引号引起来就行
        String s1 = "hello would";

        // 直接new一个String对象
        String s2 = new String("hello would");

        //使用字符数组进行构造
        char[] array = {'h','e','l','l','o',' ','w','o','u','l','d'};
        String s3 = new String(array);

        System.out.println(s1);  
        System.out.println(s2);
        System.out.println(s3);
    }

这里我们虽然打印出的效果是一样的, 可是还是有一定区别,
注意
1.String 是引用类型, 内部并不储存字符串本身, 在String类的实现源码中, String类实例变量如下:

在这里插入图片描述

    public static void main(String[] args) {
    // s1和s2引用的是不同的对象, s1和s3引用的同一对象
    String s1 = new String("hello");
    String s2 = new String("would");
    String s3 = s1;

        System.out.println(s1.length()); //获取字符串的长度
        System.out.println(s1.isEmpty()); //如果字符串的长度为0, 返回true, 否则返回false
    }

在这里插入图片描述
2.在Java中, 用双引号引起来的也是String类
比如: “hello”

System.out.println("hello".lenth());

1.2 String对象的比较

字符串的比较是比较常见的操作之一, 比如: 字符串比较,
Java提供4中比较方法:

1. 利用 == 比较是否引用同一对象

注意: 对于内置对象, ==比较的是内在的值, 而引用类型, == 比较的是引用中的地址

public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = 10;
        System.out.println(a==b); // false
        System.out.println(a==c); // true

        String s1 = new String("hello");
        String s2 = new String("would");
        String s3 = new String("hello");
        String s4 = s1;
        System.out.println(s1==s2); //false
        System.out.println(s1==s3); //false
        System.out.println(s1==s4); //true
    }

2. 利用equals() 方法比较

首先我们看一下这个方法的源码
在这里插入图片描述

String类重写的父类Object的equals方法, Object中equals方法默认按照==比较, String重写了equals方法后, 就是按照上述源码中的方法比较, 下面我们具体来看:

public boolean equals(Object anObject) {
//1. 检测this 和anObject 是否为同一对象, 如果是返回true
        if (this == anObject) {
            return true;
        }

// 2. 检测anObject 是否为String类型的对象, 如果是继续比较, 否则返回false 
        if (anObject instanceof String) {
//   anObject 向下转型为String类型的对象
            String anotherString = (String)anObject;
            int n = value.length;
// 3. this 和 anObject两个字符串的长度是否相同, 是则继续比较, 否则返回true
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
// 4. 按照字典序, 从前往后依次进行比较
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

下面我们看一个实例:

 public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("hello");
        String s3 = new String("would");
        // s1 s2 s3 分别引用的是不同的对象, 所以==比较结果全是false
        System.out.println(s1==s2); //false
        System.out.println(s1==s3); //false

        //equals 比较, String对象中的各个字符
        //虽然s1和s2引用的不是一个对象, 但是它们两个对象中存放的内容是相同的, 所以输出true
        //s1和s3 不是一个对象, 而且两个对象存放的内容也不同, 所以输出false
        System.out.println(s1.equals(s2)); //true
        System.out.println(s1.equals(s3)); //false
    }

3. 利用compareTo 方法比较两个字符串的

与equals方法不同的是, equals返回的是boolean类型, compareTo方法返回的是int类型.
具体比较方式:
1.先按照字典序大小比较, 出现不等的字符, 直接返回这两个字符的大小差值.
2.如果前k个字符相等(k为这两个字符串的长度最小值),返回这两个字符串的长度差

    public static void main(String[] args) {
        String s1 = new String("abc");
        String s2 = new String("aBc");
        String s3 = new String("aD");
        String s4 = new String("abcdef");
        String s5 = new String("ab");

        System.out.println(s1.compareTo(s2)); //第二个字符不相等, 返回这两个字符的差值32
        System.out.println(s1.compareTo(s3)); //第二个字符不相等, 返回这两个字符的差值30
        System.out.println(s1.compareTo(s4)); //前k个字符都相等, 返回这两个字符串的长度差-3
        System.out.println(s1.compareTo(s5)); //前k个字符都相等, 返回这两个字符串的长度差1
    }

4.利用compareToIgnoreCase方法比较(忽略大小写)

    public static void main(String[] args) {
        String s1 = new String("abc");
        String s2 = new String("aBc");
        String s3 = new String("aD");
        String s4 = new String("abcdef");
        String s5 = new String("ab");

        System.out.println(s1.compareToIgnoreCase(s2));  //0
        System.out.println(s1.compareToIgnoreCase(s3));  //-2
        System.out.println(s1.compareToIgnoreCase(s4));  //-3
        System.out.println(s1.compareToIgnoreCase(s5));  //1
    }

1.3字符串查找

字符串查找也是字符串中非常常见的操作, String类提供的常见的查找方法:

方法功能
char charAt(int index)返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常
int indexOf(int ch)返回ch第一次出现的位置,没有返回-1
int indexOf(int ch, intfromIndex)从fromIndex位置开始找ch第一次出现的位置,没有返回-1
int indexOf(String str)返回str第一次出现的位置,没有返回-1
int indexOf(String str, intfromIndex)从fromIndex位置开始找str第一次出现的位置,没有返回-1
int lastIndexOf(int ch)从后往前找,返回ch第一次出现的位置,没有返回-1
int lastIndexOf(int ch, intfromIndex)从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返回-1
int lastIndexOf(String str)从后往前找,返回str第一次出现的位置,没有返回-1
int lastIndexOf(String str, intfromIndex)从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返回-1
 public static void main(String[] args) {
        String s = new String("aabbccdefgh");
        System.out.println(s.charAt(4)); //打印你所查找位置的上的元素c
        System.out.println(s.indexOf("b")); //打印你查找的元素第一次出现的位置2
        System.out.println(s.indexOf("b", 3)); //从你所选位置开始查找你所需元素 3
        System.out.println(s.indexOf("bcc"));//打印你查找的字符串第一次出现的位置3
        System.out.println(s.lastIndexOf("c")); //从后往前找,第一次出现的位置5
        System.out.println(s.lastIndexOf("b", 2));//从你所选位置从后往前找

    }

**注意:**上述方法都是实例方法

1.4转化

1. 数值和字符串的转化

public static void main(String[] args) {
        //数字转字符串
        String s1 = String.valueOf(1234);  //int
        String s2 = String.valueOf(12.32);  //double
        String s3 = String.valueOf(true);  //boolean
        //字符串转数字
        int data1 = Integer.parseInt("1234");
        double data2 = Double.parseDouble("20.23");
        System.out.println(s1); 
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(data1);
        System.out.println(data2);
    }

2. 大小写转化

public static void main(String[] args) {
        String s1 = new String("HELLO");
        String s2 = new String("would");
        System.out.println(s1.toLowerCase());  //hello
        System.out.println(s2.toUpperCase());  //WOULD
    }

3. 字符串转数组

public static void main(String[] args) {
   String s1 = new String("HELLO WOULD");
   //字符串转数组
   char[] ch = s1.toCharArray();
       for (int i = 0; i < ch.length; i++) {
           System.out.println(ch[i]);
       }
       System.out.println("=============================");
       // 字符串转数字
       int data1 = Integer.parseInt("1234");
       double data2 = Double.parseDouble("12.14");
       System.out.println(data1+1); //1235
       System.out.println(data2+0.1);//12.24
   }

4. 格式化

public static void main(String[] args) {
        String s = String.format("%d-%d-%d", 2023, 04,18);
        System.out.println(s);
    }

1.5 字符串的替换

使用一个指定的字符串替换掉已有的字符串数据,方法如下:

方法功能
String replaceAll(String regex, String replacement)替换所有的指定内容
String replaceFirst(String regex, String replacement)替换首个内容

代码示例:

public static void main(String[] args) {
        //字符串的替换
        String str = "hello";
        System.out.println(str.replaceAll("l", "8"));
        System.out.println(str.replaceFirst("l", "8"));
    }

这里我们需要注意的是:字符串是一个不可变对象替换的时候不修改原来的字符串, 而是产生一个新的字符串

1.6 字符串拆分

就是将一个完整的字符串按照指定的分隔符划分为若干个子字符串.

方法功能
String[] split(String regex)将字符串全部拆分
String[] split(String regex, int limit)将字符串以指定的格式,拆分为limit组

实现字符串的拆分处理:

public static void main(String[] args) {
        //字符串的拆分
        String str = "hello would hello would";
        String[] result = str.split(" "); //按照空格拆分
        for (String s:result) {
            System.out.println(s);
        }
    }

字符串的部分拆分

public static void main(String[] args) {
        //字符串的部分拆分
        String str = "hello would hello would";
        String[] split = str.split(" ",3);    //按空格分为三部分
        for (String s:split) {
            System.out.println(s);
        }

拆分是特别常见的操作, 我们一定要重点掌握,

还有一些特殊字符作为分隔符可能不能做出正确的拆分, 需要加上转义
拆分ip地址

String str = "192.168.1.1" ;
String[] result = str.split("\\.") ;   //这里我们就要用到转义字符才能正确分割
for(String s: result) {
  System.out.println(s);
}

注意事项:

  1. 字符"|“, “.”, “*”, “+”; 前面加上”\"
  2. 二如果是"“, 那就得写成”\\"
  3. ** 如果字符串中有多个分隔符, 用"|"作为连字符**

多次拆分

public static void main(String[] args) {
        //字符串的多次拆分
        String str = "name=张三&age=18";
        String[] result = str.split("&");
        for (int i = 0; i < result.length; i++) {
            String[] temp = result[i].split("=");
            System.out.println(temp[0]+"="+temp[1]);
        }

1.7 字符串截取

从一个完整字符串截取出部分内容

方法功能
String substring(int beginIndex)从指定索引截取到结尾
String substring(int beginIndex, int endIndex)截取部分内容
public static void main(String[] args) {
        String str = "hellowould";
        System.out.println(str.substring(5));  //would
        System.out.println(str.substring(0, 5));  // hello
    }

注意:

  1. 索引从0开始
  2. 这里的写法是**前闭后开**, substring(0,5),表示包含0下标的值, 不包括5下标的字符

1.8 其他操作方法

方法功能
String trim()去掉字符串中的左右空格,保留中间空格
String toUpperCase()字符串转大写
String toLowerCase()字符串转小写

trim方法实例:

public static void main(String[] args) {
        String str = "  hello would  ";
        System.out.println("["+str+"]");         //[  hello would  ]
        System.out.println("["+str.trim()+"]");  //[hello would]
    }

字符转大小写实例

public static void main(String[] args) {
        //字符串大小写转化
        String str = "12abc&^%*34DEF";
        System.out.println(str.toUpperCase());  //12ABC&^%*34DEF
        System.out.println(str.toLowerCase());  //12abc&^%*34def
    }

注意:

这两个函数只转换字母

1.9 字符串常量池

1.9.1 创建对象的思考

public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        String str3 = new String("hello");
        String str4 = new String("hello");
        System.out.println(str1==str2);  //true
        System.out.println(str1==str3);  //false
        System.out.println(str3==str4);  //false
    }

上面我们创建方法类似, 为什么s1和s2 引用的是同一个对象, 而s3 和s4 不是呢?

在java程序中, 类似于:1, 2, 3, 4, 5, 6, 3.14 “hello” 等字面类型的常量会经常频繁的使用, 为了使程序运行的更快, 更节省内存,java为8种基本数据类型和String类都提提供了常量池.

为了节省存储空间和提高程序的运行效率, Java中引入了:

  1. **Class文件常量池:**每个Java源文件编译后生成 .class文件中会保存当前类中的字面常量和字符信息
  2. **运行时常量池:**在.class文件被加载时, .class文件中的常量池被加载到内存中被称为运行时常量池, 运行时常量池每个类都有一份.
  3. 字符串常量池

2. 字符串修改

在这里我们首先要知道:
在这里插入图片描述
在这里插入图片描述

  1. String类在设计时就是不可改变的,String类实现描述就已经说明了
  2. String类中的字符实际保存在内部维护的value字符数组中
  3. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
  4. final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内
    容是可以修改的(返回创建的新对象)。

那为什么我们还要谈字符串修改呢?
原因是:我们应该**尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率
非常低下
**。

public static void main(String[] args) {
        String str = "hello";
        str += "would";
        System.out.println(str);  // hellowould
    }

这种方法不推荐使用, 其效率非常低下, 中间创建了许多临时对象
下面我们做一个对比

public static void main(String[] args) {
        //传统修改字符串的方式
        long start = System.currentTimeMillis(); //开始时间
        String str = "0";
        for (int i = 0; i < 100000; i++) {
            str += i;
        }
        long end = System.currentTimeMillis();  //结束时间
        System.out.println(end-start);   //修改完用时:18619

        //StringBuffer
        start = System.currentTimeMillis();
        StringBuffer str1 = new StringBuffer("0");
        for (int i = 0; i < 100000; i++) {
            str1.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println(end-start);   //修改完用时:2

        //StringBuilder
        start = System.currentTimeMillis();
        StringBuilder str2 = new StringBuilder("0");
        for (int i = 0; i < 100000; i++) {
            str2.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println(end-start);   //修改完用时:1
    }

在这里我们可以看出, 在对String类进行修改的时候, 效率是非常慢的, 因此我们要尽量对String的直接修改, 如果要修改, 建议使用StringButter和StringBuilder

2.1 StringBuilder和StringBuffer

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大
部分功能是相同的,下面介绍 StringBuilder常用的一些方法,其它需要用到了大家可参阅StringBuilder在线文档

方法功能
StringBuff append(Stringstr)在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、
double、float、int、long、Object、String、StringBuff的变量
char charAt(int index)获取index位置的字符
int length()获取字符串的长度
int length()获取字符串的长度
int capacity()获取底层保存字符串空间总的大小
mininmumCapacity)扩容
void setCharAt(int index,char ch)将index位置的字符设置为ch
int indexOf(String str)返回str第一次出现的位置
int indexOf(String str, intfromIndex)从fromIndex位置开始查找str第一次出现的位置
int lastIndexOf(String str)返回最后一次出现str的位置
int lastIndexOf(String str,
int fromIndex)从fromIndex位置开始找str最后一次出现的位置
StringBuff insert(intoffset, String str)在offset位置插入:八种基类类型 & String类型 & Object类型数据
StringBuffer
deleteCharAt(int index)删除index位置字符
StringBuffer delete(intstart, int end)删除[start, end)区间内的字符
StringBuffer replace(int
start, int end, String str)将[start, end)位置的字符替换为str
String substring(int start)从start开始一直到末尾的字符以String的方式返回
String substring(int
start,int end)将[start, end)范围内的字符以String的方式返回
StringBuffer reverse()反转字符串
String toString()将所有字符按照String的方式返回
public static void main(String[] args) {
        //字符串修改的应用
        StringBuffer sb1 = new StringBuffer("hello");
        StringBuffer sb2 = sb1;
        sb1.append(' ');     //尾插
        sb1.append("would");
        System.out.println(sb1);  //hello would
        sb1.append(1234);
        System.out.println(sb1);  //hello would1234
        System.out.println(sb1==sb2);  //true
        System.out.println(sb2);  //hello would1234
        System.out.println(sb1.charAt(0));  //获取0位置上的字符 h
        System.out.println(sb1.length());  //获取字符串的有效长度
        System.out.println(sb1.capacity()); //获取底层数组的总大小
        sb1.setCharAt(0,'H');  // 设置任意位置上的字符
        sb1.insert(0,"hello would"); //设置任意位置的字符,可一改多
        System.out.println(sb1);
        sb1.append("hello would");
        System.out.println(sb1.indexOf("hello")); //获取hello第一次出现的位置
        System.out.println(sb1.lastIndexOf("hello"));// 获取hello最后出现的位置
        System.out.println(sb1);  //输出sb1 hello wouldHello would1234hello would
        sb1.delete(0,5);  //删除[0,5)的上的字符
        String ret = sb1.substring(3,6);  //截取[3.6)上的字符, 返回给ret
        System.out.println(sb1);  // wouldHello would1234hello would
        sb1.reverse();  //字符串逆转
        System.out.println(sb1);  //dluow olleh4321dluow olleHdluow
        sb1.toString(); //将StringBuffer以String的方式返回
        System.out.println(sb1);
    }

从上述例子可以看出:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可
以修改。频繁修改字符串的情况考虑使用StringBuilder。

注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:
String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
StringBuilder变为String: 调用toString()方法。

2.2 面试题

  1. String、StringBuffer、StringBuilder的区别
  1. String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
  2. StringBuffer与StringBuilder大部分功能是相似的
  3. StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北冥有鱼-.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值