【Java SE语法篇】10.String类

简介: 【Java SE语法篇】10.String类


前言

在程序开发中经常会用到字符串。字符串是指一连串的字符,它是由许多单个字符连接而成的,如多个英文字母所组成的英文单词。字符串可以包含任意字符,这些字符必须包含在一对双引号""之内,例如:“abc”。Java定义了3个封装字符串的类,分别是String类、StringBuffer类和StringBulider类。它们位于java.lang 包中,并提供了一系列操作字符串的方法,这些方法不需要导包就可以直接使用。下面将对String类、StringBuffer类和StringBulider类进行讲解。

1. String类

1.1 字符串的构造

String类提供了构造方法非常多,常用的就以下三种:

public class Main {
    public static void main(String[] args) {
        // 使用常量串构造
        String s1 = "hello";
        System.out.println(s1);
        // 直接new String对象
        String s2 = new String("hello");
        System.out.println(s2);
        // 使用字符数组进行构造
        char[] chars = {'h','e','l','l','o'};
        String s3 = new String(chars);
        System.out.println(s3);
    }
}

其他方法需要用到时,大家参考Java在线文档:String官方文档

【注意】:

  1. String是引用类型,内部并不存储字符串本身,在String类的实现源码中,String类实例变量如下:
public class Main {
    public static void main(String[] args) {
        // s1和s2引用的是不同对象  s1和s3引用的是同一对象
        String s1 = new String("hello");
        String s2 = new String("world");
        String s3 = s1; // s3这个引用指向了s1这个引用的对象
        System.out.println(s3); // hello
        System.out.println(s1.length());// 获取字符串的长度
        System.out.println(s1.isEmpty());// 如果字符串长度为0,返回true,否则返回false
        String s4 = "";
        System.out.println(s4.length()); // 0
        System.out.println(s4.isEmpty());// true
}
  1. 内存图:

  1. 在Java中""引起来的也是String类型对象
// 打印"hello"字符串(String对象)的长度
System.out.println("hello".length());// 5

1.2 String对象的比较

字符串的比较是常见操作之一,比如:字符串排序。Java中总共提供了4种方式:

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

注意:对于内置类型,==比较的是变量中的值;对于引用类型==比较的是引用中的地址。

public class Main {
    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("hello");
        String s3 = new String("world");
        String s4 = s1;
        System.out.println(s1 == s2);   // false
        System.out.println(s2 == s3);   // false
        System.out.println(s1 == s4);   // true
    }
}

2. equals()方法:按照字典序比较

字典序:字符大小的顺序

String类重写了父类Objectequals方法,Objectequals默认按照==比较,String重写equals方法后,按照 如下规则进行比较,比如:s1.equals(s2)

public class Main {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("hello");
        String s3 = new String("Hello");
        // 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
    }
}

【注意】:为什么以下代码输出的结果都是true

答:因为在 Java 中有一块特殊的内存(常量池),存储在堆上。

它的作用是什么呢?

  1. 只要是""双引号括起来的字符串存放在这里。
  2. 存储字符串之前它会找常量池里是否存在这个字符串,如果有就不存放了(常量池不会重复存放相同的值),所以上述代码中s1s2都指向常量池hello的地址。

3. compareTo()方法: 按照字典序进行比较

equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。具体比较方式:

  1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
  2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值
public class Main {
    public static void main(String[] args) {
        String s1 = new String("abc");
        String s2 = new String("ac");
        String s3 = new String("abc");
        String s4 = new String("abcdef");
        // s1 和 s2 比较大小 s1 > s2 返回大于0的数字 s1 < s2 返回小于0的数字 否则返回0
        // 返回差值就是对应acsii码的差值
        System.out.println(s1.compareTo(s2));   // 不同输出字符差值-1
        System.out.println(s1.compareTo(s3));   // 相同输出 0
        System.out.println(s1.compareTo(s4));   // 前k个字符完全相同,输出长度差值 -3
    }
}

4. 忽略大小写比较

  • equalsIgnoreCase()方法:与equals()方式相同,但是忽略大小写比较。
  • compareToIgnoreCase()方法:与compareTo()方式相同,但是忽略大小写比较。
public class Main {
    public static void main(String[] args) {
        String s1 = new String("abc");
        String s2 = new String("Abc");
        System.out.println(s1.equals(s2)); // false
        System.out.println(s1.equalsIgnoreCase(s2)); // true
        System.out.println(s1.compareTo(s2));//32
        System.out.println(s1.compareToIgnoreCase(s2));// 0
    }
}

1.3 字符串查找

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

方法 功能
char charAt(int index) 返回index位置上字符,如果index为负数或者越界,抛出 IndexOutOfBoundsException异常
int indexOf(int ch) 返回ch第一次出现的位置,没有返回-1
int indexOf(int ch, int fromIndex) 从fromIndex位置开始找ch第一次出现的位置,没有返回-1
int indexOf(String str) 返回str第一次出现的位置,没有返回-1
int indexOf(String str, int fromIndex) 从fromIndex位置开始找str第一次出现的位置,没有返回-1
int lastIndexOf(int ch) 从后往前找,返回ch第一次出现的位置,没有返回-1
int lastIndexOf(int ch, int fromIndex) 从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返 回-1
int lastIndexOf(String str) 从后往前找,返回str第一次出现的位置,没有返回-1
int lastIndexOf(String str, int fromIndex) 从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返 回-1
public class Main {
    public static void main(String[] args) {
        String s1 = new String("hello");
        // 返回字符串对应下标的字符
        System.out.println(s1.charAt(1)); // e
        //返回对应字符出来的下标位置 从头开始查找
        System.out.println(s1.indexOf('e')); // 1
        //返回对应字符出来的下标位置 从指定位置查找
        System.out.println(s1.indexOf('l', 3)); // 3
        // 字符串查找 从一个字符串找另一个字符串
        System.out.println(s1.indexOf("llo")); // 2
        System.out.println(s1.indexOf("ll", 2));// 2
        // 返回对应字符出来的下标位置 从尾开始向前查找
        System.out.println(s1.lastIndexOf('l'));// 3
        // 返回对应字符出来的下标位置 从指定位置向前查找
        System.out.println(s1.lastIndexOf('l', 1));// -1
        System.out.println(s1.lastIndexOf("ll")); // 2
        System.out.println(s1.indexOf("ll", 1));// 2
    }
}

1.4 转换

1. 数值和字符串转化

public class Main {
    public static void main(String[] args) {
        // 数字转字符串
        String s1 = String.valueOf(123);
        System.out.println(s1);
        String s2 = String.valueOf(12.34);
        System.out.println(s2);
        String s3 = String.valueOf(true);
        System.out.println(s3);
        // 字符串转数字
        int num1 = Integer.parseInt("1234");
        System.out.println(num1);
        
        double num2 = Double.parseDouble("12.34");
        System.out.println(num2);
    }
}

2. 大小写转化

public class Main {
    public static void main(String[] args) {
        // 小写转大写
        String s1 = "hello";
        System.out.println(s1.toUpperCase());
        // 大写转小写
        String s2 = "HELLO";
        System.out.println(s2.toLowerCase());
    }
}

问题:转化为大写/小写是在原来的字符串上进行修改的?

答:不是!!!,转化为大写/小写之后,是产生了一个新的对象

通过String类源码中的toUpperCase()方法和toLowerCase()方法返回的都是一个新的字符串。

验证:


3. 字符串转数组

public class Main {
    public static void main(String[] args) {
        // 字符串转数组
        String s1 = "hello";
        char[] chars = s1.toCharArray();
        for (char ch  : chars) {
            System.out.println(ch);
        }
        
        // 数组为字符串
        String s2 = new String(chars);
        System.out.println(s2);
    }
}

4. 格式化

public class Main {
    public static void main(String[] args) {
        String s1 = String.format("%d-%d-%d",2021,5,19);
        System.out.println(s1);
    }
}

1.5 字符串替换

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

方法 说明
String replaceAll(String regex, String replacement) 替换所有的指定内容
String replaceFirst(String regex, String replacement) 替换收个内容
public class Main {
    public static void main(String[] args) {
        String s1 = "abcabcdeabcd";
        System.out.println(s1.replace('a', 'p')); // pbcpbcdepbcd
        System.out.println(s1.replace("ab","haha")); // hahachahacdehahacd
        System.out.println(s1.replaceAll("ab", "uuu")); // uuucuuucdeuuucd
        System.out.println(s1.replaceFirst("ab", "ha")); // hacabcdeabcd
    }
}

1.6 字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。

方法 功能
String[] split(String regex) 将字符串全部拆分
String[] split(String regex, int limit) 将字符串以指定的格式,拆分为limit组
public class Main {
    public static void main(String[] args) {
        String s1 = "name = zhangsan&age = 18";
        String[] strings = s1.split("&");
        for (int i = 0; i < strings.length; i++) {
            System.out.println(strings[i]);
        }
        
        String s2 = "Hello handsome hello beautiful give me some attention"; 
        // 帅哥美女点点关注
        String[] strings1 = s2.split(" ",12); 
        // 虽然不能分割12次 但是它能够保证能分割的最大次数 不够就不分了
        for (int i = 0; i < strings1.length; i++) {
            System.out.println(strings1[i]);
        }
    }
}

特殊情况:

public class Main {
    public static void main(String[] args) {
        String s1 = "192.168.1.2";
        String[] strings = s1.split("\\.");
        for (int i = 0; i < strings.length; i++) {
            System.out.println(strings[i]);
        }
        System.out.println("=========");
        String s2 = "C:\\APP\\Java\\jdk1.8\\bin\\java.exe";
        String[] strings1 = s2.split("\\\\");
        for (int i = 0; i < strings1.length; i++) {
            System.out.println(strings1[i]);
        }
        System.out.println("=========");
        
        String s3 = "name=zhangsan&age=18";
        String[] strings2 = s3.split("&|=");
        for (int i = 0; i < strings2.length; i++) {
            System.out.println(strings2[i]);
        }
    }
}

【注意事项】:

  1. 字符"|“,”*“,”+“都得加上转义字符,前面加上”\".
  2. 而如果是"“,那么就得写成”\\".
  3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.

多次拆分:

public class Main {
    public static void main(String[] args) {
        String s1 = "name=zhangsan&age=18";
        String[] strings = s1.split("&");
        for (String x:strings) {
            String[] strings2 = x.split("=");
            for (String x1 :strings2) {
                System.out.println(x1);
            }
        }
    }
}

1.7 字符串的截取

从一个完整的字符串之中截取出部分内容。可用方法如下:

方法 功能
String substring(int beginIndex) 从指定索引截取到结尾
String substring(int beginIndex, int endIndex) 截取部分内容
public class Main {
    public static void main(String[] args) {
        String s1 = "helloworld" ;
        System.out.println(s1.substring(5)); // world
        System.out.println(s1.substring(0, 5)); 
        // hello 包含 0 下标的字符, 不包含 5 下标
    }
}

1.8 其他操作

方法 功能
String trim() 去掉字符串中的左右空格,保留中间空格

代码案例:trim()方法:

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

trim 会去掉字符串开头和结尾的空白字符(空格, 换行, 制表符等).

2. StringBuilde 类 和 StringBuffer类

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilderStringBuffer类。这两个类大 部分功能是相同的,这里介绍 StringBuilder常用的一些方法,其它需要用到了大家可参阅 [StringBuilder在线文档](Overview (Java Platform SE 8 ) (oracle.com))

方法 功能
StringBuff append(String str) 在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、 double、float、int、long、Object、String、StringBuff的变量
char charAt(int index) 获取index位置的字符
int length() 获取字符串的长度
int capacity() 获取底层保存字符串空间总的大小
void ensureCapacity(int mininmumCapacity) 扩容
void setCharAt(int index, char ch) 将index位置的字符设置为ch
int indexOf(String str) 返回str第一次出现的位置
int indexOf(String str, int fromIndex) 从fromIndex位置开始查找str第一次出现的位置
int lastIndexOf(String str) 返回最后一次出现str的位置
int lastIndexOf(String str, int fromIndex) 从fromIndex位置开始找str最后一次出现的位置
StringBuff insert(int offset, String str) 在offset位置插入:八种基类类型 & String类型 & Object类型数据
StringBuffer deleteCharAt(int index) 删除index位置字符
StringBuffer delete(int start, 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 class Main {
    public static void main(String[] args) {
        StringBuilder sb1 = new StringBuilder("hello");
        StringBuilder sb2 = sb1;
        // 追加:即尾插-->字符、字符串、整形数
        sb1.append(' ');                  // hello
        sb1.append("world");              // hello world
        sb1.append(123);                  // hello world123
        System.out.println(sb1);          // hello world123
        System.out.println(sb1 == sb2);   // true
        System.out.println(sb1.charAt(0));   // 获取0号位上的字符  h
        System.out.println(sb1.length());    // 获取字符串的有效长度14
        System.out.println(sb1.capacity());  // 获取底层数组的总大小
        sb1.setCharAt(0, 'H');     // 设置任意位置的字符 Hello world123
        sb1.insert(0, "Hello world!!!");         // Hello world!!!Hello world123
        System.out.println(sb1);
        System.out.println(sb1.indexOf("Hello"));          // 获取Hello第一次出现的位置
        System.out.println(sb1.lastIndexOf("hello"));  // 获取hello最后一次出现的位置
        sb1.deleteCharAt(0);                               // 删除首字符
        sb1.delete(0,5);                                   // 删除[0, 5)范围内的字符
        String str = sb1.substring(0, 5);                  // 截取[0, 5)区间中的字符以String的方式返回
        System.out.println(str);
        sb1.reverse();                      // 字符串逆转
        str = sb1.toString();               // 将StringBuffer以String的方式返回
        System.out.println(str);
    }
}

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

注意:StringStringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:

  • String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
  • StringBuilder变为String: 调用toString()方法。
相关文章
|
27天前
|
Java 测试技术 开发者
Java零基础-indexOf(String str)详解!
【10月更文挑战第14天】Java零基础教学篇,手把手实践教学!
111 65
|
2天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
|
19天前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
41 17
|
11天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
15天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
55 4
|
16天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
34 2
|
20天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
24天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
24天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
24天前
|
存储 Java 编译器
java wrapper是什么类
【10月更文挑战第16天】
27 3

热门文章

最新文章

下一篇
无影云桌面