java字符串及其特性和内置函数

0 阅读6分钟

字符串介绍

  • 字符串被创建后可以理解为是一个字符串对象,左边的引用只是当前字符串变量的管理者(或者叫指针对象),而变量类型(string)则被称为字符串的类,右边则为字符串对象,同时字符串也和数组一样是引用数据类型
//定义字符串的两种方式 
String h= "hello World";//更常用,这种定义方式可以称为“字面量”
String h = new String("hello world");//这是不是有点像数组的创建方法,没错字符串就是一种特殊的数组
  • 我们也可以读取用户输入的字符串
//读取用户输入的字符串 
//读取空格、回车、\t(tab)之前的数据
String next = scanner.next(); 
//一整行(即为忽略空格和制表符tab)
String nextLine = scanner.nextLine();
  • 因为字符串也是一种特殊的数组,即也为引用数据类型,所以不可以用字符串的变量名(引用名)对比两个字符串是否相等进行比较,因为字符串引用名存放的实际上是字符串存放的地址,比较字符串名相当于比较字符串存放的地址,两个字符串存放的地址肯定是不同的,所以这样比较返还必为false
String hello2 = new String("Hello World");
String hello3 = new String("Hello World");
//对比hello2和hello3的内存地址,换句话说,是在对比,这两个变量指向的是不是同一个对象
System.out.println(hello2 == hello3);//false
  • 和数组一样java也为我们提供了对比两个字符串是否相等的方法
String hello2 = new String("Hello World");
String hello3 = new String("Hello World");
//使用hello2字符串对象中继承而来的equals方法
System.out.println(hello2.equals(hello3));//true
  • 同样像数组一样我们也不可以通过赋值字符串变量名来对字符串进行复制
String hello2 = new String("Hello World");
String hello4 = hello2;
System.out.println(hello2 == hello4);//true
//返回为true说明这两个数组变量指向了同一块内存空间,这显然是一个错误的复制操作

字符串常量池

  • 使用""去定义字符串,这种形式就会被java当成是常量,会被放在常量池当值
  • 常量池类似于C语言的全局/静态区 (Global/Static Area)和文字常量区 (Literal Constant Area)
String hello5 = "Hello World";
String hello6 = "Hello World";
  • 同时JVM为了减少对于内存空间的浪费会将在常量池中的两个相同的字符串合并到一起,使得多个字符串的字符串名同时指向一块内存空间,如下方代码所示
String hello5 = "Hello World";
String hello6 = "Hello World";
System.out.println(hello5 == hello6); //true
//两个字符串变量是相等的说明它们引用的是同一块内存空间

两种创建字符串的区别

  • 实际上使用new关键字的字符串的内容也是存放在常量池中的,当使用 new String("hello") 创建字符串时,尽管字符串字面量 "hello" 存储在字符串常量池中,但 new 关键字会导致在堆上创建一个新的 String 对象。这个对象包含一个指向常量池中 "hello" 的引用。这种方式不会检查字符串常量池中是否已经存在相同的字符串,总是会在堆上创建一个新的对象。

image.png

  • 而对于字面量创建,当你使用字符串字面量创建字符串时,例如 String s = "hello";,这个字符串实际上是存储在字符串常量池中的。字符串常量池是方法区内的一块内存区域,通常与类的其他信息一起存储。这种方式创建的字符串会检查字符串常量池中是否存在相同的字符串字面量,如果存在,则返回那个字符串的引用;否则,会在常量池中创建一个新的字符串。

image.png

字符串可以修改吗

不能直接修改

  • 在java中字符串是不可以修改的,无论是字符串字面量创建,还是使用new关键字创建,因为这两种方法一旦创建字符串的值都会放入常量池中,因此在String类中就没有给我们修改字符串的方法

修改字符串的方法

方法一:强制转换为字符型数组

public class ModifyStringExample {
    public static void main(String[] args) {
        String str = "Hello";
        char[] charArray = str.toCharArray(); // 将字符串转换为字符数组

        // 修改第 2 个字符(索引为 1)
        charArray[1] = 'a';

        // 将字符数组转换回字符串
        String modifiedStr = new String(charArray);
        System.out.println(modifiedStr); // 输出 "Hallo"
    }
}

方法二:使用StringBuffer或StringBuilder类

  • StringBuffer和StringBuilder类是可变字符串类型,允许直接修改字符串字符
  • 但两个类性能消耗较大
public class ModifyStringExample {
    public static void main(String[] args) {
        String str = "Hello";
        StringBuilder sb = new StringBuilder(str); // 将字符串转换为 StringBuilder

        // 修改第 2 个字符(索引为 1)
        sb.setCharAt(1, 'a');

        // 将 StringBuilder 转换回字符串
        String modifiedStr = sb.toString();
        System.out.println(modifiedStr); // 输出 "Hallo"
    }
}

方法三:使用字符串拼接

public class ModifyStringExample {
    public static void main(String[] args) {
        String str = "Hello";

        // 修改第 2 个字符(索引为 1)
        String modifiedStr = str.substring(0, 1) + 'a' + str.substring(2);

        System.out.println(modifiedStr); // 输出 "Hallo"
    }
}

字符串内置函数(常用操作)

内置函数概念

  • 字符串被定义出来的时候可以说是一个String类的对象,每次创建时我们都要使用new String()来创建对象,在字符串对象中继承了类中的很多方法,我们称之为字符串的内置函数(字符串的常用操作),比如:
//这里就是使用hello2字符串对象从类中中继承而来的equals方法
System.out.println(hello2.equals(hello3));//true
//所以equals方法的原型为equals(String),equal方法的代码在String类中
//实际上换成这样也是可以的
System.out.println(hello3.equals(hello2));
//任然为True

字符串的常用内置函数

获取长度

  • 获取字符串长度
System.out.println(hello2.length());//11

获取位置

通过字符找下标
  • 查到返回下标,没有查到返回-1
  • 获取字符/字符串在字符串中第一次出现的位置(下标)
String hello2 = new String("Hello World");
System.out.println(hello2.indexOf('o'));//4
ystem.out.println(hello2.indexOf("wor"));//6
  • 那想要获得非第一次出现的位置要咋做,实际上只需要给indexof传入一个整型值告诉它从上一次找到的位置开始下一次查找,依次类推
String hello2 = new String("Hello World");
int temp = hello2.indexOf("o");
System.out.print(hello2.indexOf("o",temp+1));

//我们还可以实际一个循环,让此算法自动帮我们获取所有该字母”o“的位置(下标)
String hello2 = new String("Hello World");  
int temp;  
temp = hello2.indexOf("o");  
while(temp != -1){  
    System.out.println(temp);  
    temp = hello2.indexOf("o",temp+1);  
}
通过下标找字符
  • 通过下标找字符
System.out.println(hello2.charAt(4));//o
//当传入的下标越界会保存

替换操作

  • 替换操作并不会更改原先的字符串,而是会返回一个替换后的新字符串
String newHello2 = hello2.replace("ld","llld");
System.out.println(newHello2); //Hello Worllld

截取操作

  • 类型于pytho的切片操作,并不会改变原来的字符串而是返回一个新的字符串
String hello2 = new String("Hello World");
System.out.println(hello2.substring(3));  //lo World
System.out.println(hello2.substring(3,6)); //lo
System.out.println(hello2); //Hello World

转换大小写的操作

  • 转换大小写,并不会改变原来的字符串而是返回一个新的字符串
String hello2 = new String("Hello World");
System.out.println(hello2.toUpperCase());//HELLO WORLD
System.out.println(hello2.toLowerCase());//hello world
System.out.println(hello2);//Hello World

6ed2bcfdbe526e31710309a908aa557fc396eff7.jpg@1256w_888h_!web-article-pic.webp