java中String类(详解版)

String 类

1.String类的重要性

前言:在C语言中我们已经涉及到字符串了,但是在C语言中表示字符串比较麻烦,只能使用字符数组或者字符指针,并且还可以通过一系列的标准库对字符串完成大部分操作,但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想,而字 符串应用又非常广泛,因此Java语言专门提供了String类。

2.常用方法

2.1字符串构造方法

字符串构造方法主要有三种:

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

注意

  • 当我们调试这段代码时,会发现s1字符串是由value和hash组成的

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qEr9Cdcn-1683631848086)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230504231602512.png)]

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uvf160dU-1683631848087)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230504231818127.png)]
  • 由上可以看出,String是引用类型其内部并不存储字符串本身

  • 例如;

  • public static void main(String[] args) {
        // s1和s2引用的是不同对象 s1和s3引用的是同一对象
        String s1 = new String("hello");
        String s2 = new String("world");
        String s3 = s1;
        System.out.println(s1.length()); // 获取字符串长度---输出5
        System.out.println(s1.isEmpty()); // 如果字符串长度为0,返回true,否则返回false---输出false
    }
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7QR2C44F-1683631848088)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230505225139232.png)]

注意:在java中被双引号引起来的也是String类型对象。例如:

//打印hello字符串的长度
System.out.println("hello".length());

2.2 字符串的比较

对字符串常用的操作就是进行字符串比较,java中提供了四种比较方法:

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

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

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.【boolean equals(Object anObject)方法进行比较】(按照字典序进行比较,即比较字符串中的内容)

字典序:字符大小的顺序,类似于C语言中的ASCLL码大小进行比较。

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

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两个字符串的长度是否相同,是继续比较,否则返回false
    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("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
}

3.【 int compareTo(String s) 方法】( 按照字典序进行比较)

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

  1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
  2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值
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");
    System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1  注意:这里是s1减去s2,所以是-1,而不是1
    System.out.println(s1.compareTo(s3)); // 相同输出 0
    System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出长度差值 -3
}

4.【int compareToIgnoreCase(String str) 方法】(与compareTo方式相同,但是忽略大小写比较)

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");
    System.out.println(s1.compareToIgnoreCase(s2)); // 不同输出字符差值-1
    System.out.println(s1.compareToIgnoreCase(s3)); // 相同输出 0
    System.out.println(s1.compareToIgnoreCase(s4)); // 前k个字符完全相同,输出长度差值 -3
}

2.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
nt lastIndexOf(String str)从后往前找,返回str第一次出现的位置,没有返回-1
int lastIndexOf(String str, int fromIndex)从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返 回-1
public static void main(String[] args) {
    String s = "aaabbbcccaaabbbccc";
    System.out.println(s.charAt(3)); // 'b'
    System.out.println(s.indexOf('c')); // 6
    System.out.println(s.indexOf('c', 10)); // 15
    System.out.println(s.indexOf("bbb")); // 3
    System.out.println(s.indexOf("bbb", 10)); // 12
    System.out.println(s.lastIndexOf('c')); // 17
    System.out.println(s.lastIndexOf('c', 10)); // 8
    System.out.println(s.lastIndexOf("bbb")); // 12
    System.out.println(s.lastIndexOf("bbb", 10)); // 3
}

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

2.4 转化

1.【数值和字符串相互转化】(注意这里几乎都是静态方法)

class Student{
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public static void main(String[] args) {
    // 数字转字符串
    String s1 = String.valueOf(1234);
    String s2 = String.valueOf(12.34);
    String s3 = String.valueOf(true);
    String s4 = String.valueOf(new Student("Hanmeimei", 18));
    System.out.println(s1);
    System.out.println(s2);
    System.out.println(s3);
    System.out.println(s4);
    System.out.println("=================================");
    // 字符串转数字
    // 注意:Integer、Double等是Java中的包装类型,这个后面会讲到
    int data1 = Integer.parseInt("1234");
    double data2 = Double.parseDouble("12.34");
    System.out.println(data1);
    System.out.println(data2);
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e6k0DfQ4-1683631848089)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230506171210630.png)]

2.【大小写转化】

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

3.【字符串转数组】

public static void main(String[] args) {
    String s = "hello";
    // 字符串转数组
    char[] ch = s.toCharArray();
    for (int i = 0; i < ch.length; i++) {
    System.out.print(ch[i]);
	}
    System.out.println();//换行
    
    // 数组转字符串
    String s2 = new String(ch);
    System.out.println(s2);
}

4.【格式化】

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

运行结果:

1683631848089)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230506172146673.png)]

2.5 符串替换

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

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

注意:字符串的替换方法中的规则是将regex替换成replacement

例如:

  public static void main(String[] args) {
        String str1 = "aaabbb";
        String str2 = str1.replaceAll("aaa","bbb");
        System.out.println(str2);
 }

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VwaQmKtv-1683631848090)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230506172909447.png)]

这里我们要特别注意:由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串.

2.6 字符串拆分

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

主要方法有:

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

例如:

    public static void main(String[] args) {
        String str = "hhh&ooo";
        String[] ret = str.split("&");
        for (String s: ret) {
            System.out.print(s);
        }
    }

运行结果;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0UfldAER-1683631848090)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230506200251118.png)]

当我们想通过某个标志符将字符串拆分时并不是均分。例如:

public static void main(String[] args) {
        String str = "hhh&ooo&ppp";
        String[] ret = str.split("&",2);
        for (String s:ret) {
            System.out.println(s);
        }
    }

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-On91go1r-1683631848091)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230506200408374.png)]

【练习】:拆分IP地址;192.168.1.1

public static void main(String[] args) {
        String str = "192.168.1.1";
        String[] ret = str.split("\\.");
        for (String s: ret) {
            System.out.println(s);
        }
    }

注意事项:

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

【例1】:含有\\

public static void main(String[] args) {
        String str = "192\\168\\1\\1";
        String[] ret = str.split("\\\\");
        for (String s: ret) {
            System.out.println(s);
        }
    }

【例2】:多次拆分

    public static void main(String[] args) {
        String str = "hhh&eee*lll*OOO";
        String[] ret = str.split("\\*");
        for (String a:ret) {
            String[] b = a.split("&");
            for (String c: b) {
                System.out.println(c);
            }
        }
    }

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JOqyDedY-1683631848091)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230507123140006.png)]

2.7 字符串截取

字符串截取是从一个完整的字符串中截取出部分内容。

方法功能
String substring(int beginIndex)从指定索引截取到结尾
String substring(int beginIndex, int endIndex)截取部分内容

【例1】

 public static void main(String[] args) {
        String str = "helloworld" ;
        System.out.println(str.substring(5));//截取5到字符串末尾的内容
        System.out.println(str.substring(0, 5));//截取[0~5)下标的内容
    }

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-svl4cD4h-1683631848092)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230507123252662.png)]

注意事项

  1. 字符串的索引与C语言类型,也是从0开始
  2. 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标

2.8 其他操作方法

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

【例1】字符串去空格

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

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GqdjQMqR-1683631848092)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230507123704794.png)]

注意:这里的String trim()方法只能去掉字符串开头结尾的空白字符(空格, 换行, 制表符等)。

【例2】;字符串中的小写转大写

public static void main(String[] args) {
        String str = "Hello Horld";
        String ret = str.toUpperCase();
        System.out.println(ret);
    }

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gBgXXUy6-1683631848093)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230507123936194.png)]

3. 字符串常量池:

3.1创建对象的几种方式

首先我们看看下面这几个创建String对象的方式相同吗?

public static void main(String[] args) {
    String s1 = "hello";
    String s2 = "hello";
    String s3 = new String("hello");
    String s4 = new String("hello");
    System.out.println(s1 == s2); // true
    System.out.println(s1 == s3); // false
    System.out.println(s3 == s4); // false
}

上述程序创建方式类似,为什么s1和s2引用的是同一个对象,而s3和s4不是呢?

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

3.2 字符串常量池

字符串常量池在JVM中是StringTable类,实际是一个固定大小的HashTable(一种高效用来进行查找的数据结构, 后序给大家详细介绍),不同JDK版本下字符串常量池的位置以及默认大小是不同的:

3.3 String对象的创建

1.【直接使用字符串常量进行赋值】

public static void main(String[] args) {
    String s1 = "hello";
    String s2 = "hello";
    System.out.println(s1 == s2); // true
}

我们借用一幅图来理解一下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gmz4w7ru-1683631848094)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230507224559433.png)]

说明:

  • 在加载字节码文件时,"hello"字符串常量串已经就创建好了,并且保存在字符串常量池中.
  • 当String s1 = “hello”;创建对象时,首先会在字符串常量池中找,找到了就将该字符串的引用赋值给s1

2.【通过new创建String对象】

public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "abc";
        String s3 = "abc";
        String s4 = new String("abc");
        String s5 = new String("abc");
        String s6 = new String("abc");
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dNzF47Qz-1683631848094)(C:\Users\30539\AppData\Roaming\Typora\typora-user-images\image-20230509191655116.png)]

通过new创建的字符串若在常量池没有,会首先在常量池中创建该字符串,(若在常量池中有,则不会在常量池中再次创建该字符串),接着在堆区上为String对象大小开辟空间。再通过String对象指向常量池中的该字符串。

结论:只要是new的对象,都是唯一的。

  1. 【intern方法】

intern 是一个native方法(Native方法指:底层使用C++实现的,看不到其实现的源代码),该方法的作用是手动将创建的String对象添加到常量池中

public static void main(String[] args) {
        char[] ch = new char[]{'a', 'b', 'c'};
        String s1 = new String(ch); // s1对象并不在常量池中
        //s1.intern();              // s1.intern();调用之后,会将s1对象的引用放入到常量池中
        String s2 = "abc";          // "abc" 在常量池中存在了,s2创建时直接用常量池中"abc"的引用
        System.out.println(s1 == s2);
}

// 输出false
// 将上述方法打开之后,就会输出true

完结

本章的内容就到这里啦,若有不足,欢迎评论区指正,最后,希望大佬们多多三连吧,下期见!

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: JavaStringTokenizer是一个用于分解字符串的工具。它允许您将一个字符串分解成多个标记(tokens),并且可以指定分隔符。 StringTokenizer的构造函数有多个重载形式,其最常用的是: public StringTokenizer(String str, String delim) 其,str是要分解的字符串,delim是分隔符。如果不指定分隔符,则默认使用空格、制表符、换行符等空白字符作为分隔符。 StringTokenizer有三个主要的方法: 1. hasMoreTokens():判断是否还有更多的标记。 2. nextToken():返回下一个标记。 3. countTokens():返回剩余的标记数。 使用StringTokenizer可以方便地对字符串进行分解和处理,特别是在需要处理大量文本数据时,它可以提高程序的效率。 ### 回答2: java stringtokenizer是一个基于字符串分隔符的分词器。一个字符串可以有多个分隔符,而这些分隔符可以是不止一个字符的字符串。它允许程序员按照指定的分隔符对给定的字符串进行分割,返回一个分割后的字符串数组或逐个返回分隔符连接的标记。Java示例常用的分隔符是空格字符、逗号和冒号。 使用java stringtokenizer,程序员可以轻松处理字符串,将其分解成若干单词或子字符串。相对于截取字符串的方式,它具有更明确、更灵活、更高效以及更容易调试的特点。 这个通常以两个参数的构造函数来调用。第一个参数是要分解的字符串,第二个参数是包含要用作分隔符的字符的字符串。在构造函数,程序员可以选择在分割后返回空白标记,并选择将分隔符作为标记包含在返回的数组或逐个返回的标记。 如果不使用Java stringtokenizer,程序员仍可以使用String和它所包含的substring()方法和indexOf()方法来完成对字符串的分割,但java stringtokenizer提供了一种更方便和容易使用的方式来处理字符串。 在java,需要注意的是,java stringtokenizer在多线程环境下并不是线程安全的。如果多个线程同时使用同一个stringtokenizer实例,则可能会导致不可预期的结果。因此,建议在多线程环境下使用java.util.Scanner来进行字符串分割。 ### 回答3: javaStringTokenizer是一个用于将字符串分解为若干个标记的工具。它可以将一个字符串根据给定的分隔符分解成多个字符串,也可以将一个字符串根据空格、制表符或换行符等默认分隔符分解成多个字符串,起到了非常方便的作用。 StringTokenizer的主要方法有三个,分别为构造方法、nextToken()和hasMoreTokens()。其构造方法有两个重载形式,一种参数是(String str),另外一种参数是(String str,String delimiters),前者将使用默认的分隔符进行字符串分解,而后者则将指定的分隔符用于字符串分解。hasMoreTokens()方法用于判断是否还有标记未被分解,nextToken()方法用于获取下一个标记内容。 使用StringTokenizer需要结合循环来实现整个字符串的分割,下面是一个使用默认分隔符进行字符串分割的示例代码: ``` String str = "I am a boy"; StringTokenizer st = new StringTokenizer(str); while(st.hasMoreTokens()){ System.out.println(st.nextToken()); } ``` 上述代码会输出以下内容: I am a boy 在使用StringTokenizer时,需要注意以下几点: 1. 如果字符串存在多个连续分隔符,StringTokenizer默认将把它们视为一个分隔符,也就是会输出空内容的标记。如果不希望输出空内容的标记,可以使用hasMoreElements()方法代替hasMoreTokens()方法。 2. StringTokenizer属于遗留API,在Java 1.5之后推荐使用String.split()方法代替。 3. StringTokenizer是线程不安全的,如果希望在多线程环境下使用,需要做好同步处理。 JavaStringTokenizer可以快速地将字符串按照分隔符进行拆分,并且使用起来也非常简单。在一些字符串操作StringTokenizer也极为实用。不过,需要注意的是,由于StringTokenizer是一个遗留的API,使用时需要注意它的一些限制和安全性问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

这里是彪彪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值