Java常用类——String类总结

1.String类概述

1.1 String类声明

public final class String implements java.io.Serializable, Comparable<String>, CharSequence 
{
    
    
    /** The value is used for character storage. */
    private final char value[];
   ...
}
  • String是final类,不可被继承
  • String底层由char数组存储(声明为final表示不可更改)
  • String实现了Serializable接口:表示字符串支持序列化
  • String实现了Comparable接口:表示String可以比较大小

1.2 JVM中涉及字符串的内存结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3 创建String对象(以JDK8为例)

1.3.1 JVM 中堆、栈、方法区和字符串常量池

  • 堆(Heap):此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Jav虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。

  • 栈(Stack):是指虚拟机栈虚拟机栈用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char 、short 、 int 、 float 、 long 、double)、对象引用(reference类型,它不等同于对象本身,是对象在堆内存的首地址)。 方法执行完,自动释放。

  • 方法区(Method Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

  • 字符串常量池:在常量池(在方法区中)中存储字符串常量的内存空间。当需要使用字符串时,先去字符串池中查看该字符串是否已经存在,如果存在则可以直接使用,如果不存在则初始化并将该字符串放入字符串常量池中。每个字符串对象只对应1个地址(即字符串常量池中不会存储相同内容的字符串)。

1.3.2 == 和 equals()区别

           == 和 equals()区别

1.3.3 字面量方式创建String对象

String str1="abc";
String str2="abc";
s1="def";
System.out.println(s1);//def
System.out.println(s2);//abc
System.out.println(s1==s2); //true

字面量方式创建String对象可能创建0个或1个对象
如果此字符串不在字符串常量池中,则在字符串常量池中创建一个String对象,然后栈中的对象引用指向此对象的内存地址。无论以后用字面量方式创建多少个相同值的字符串对象,始终只有一个内存地址被分配。
如果此字符串存在于字符串常量池中,则对象引用直接指向此内存地址。

创建字符串对象内存结构示意图
在这里插入图片描述
在这里插入图片描述

1.3.4使用new创建String对象

String str3=new String("Java");
String str4=new String("Java");
System.out.println(str3==str4);//false

//假设Person类(有name、age属性)
Person p1 = new Person("Tom",12);
Person p2 = new Person("Tom",12);
System.out.println(p1.name.equals(p2.name));//true
System.out.println(p1.name == p2.name);//true
System.out.println(p1.age == p2.name);//true

使用new创建String对象可能创建1个或2个对象
使用new关键字肯定会在堆中创建一个String对象。
如果字符串常量池中此字符串不存在,则会在字符串常量池中创建一个此字符串对象,然后堆中对象指向此字符串地址。
如果字符串常量池中已经存在此字符串,则堆中对象直接指向此字符串地址

创建字符串对象内存结构示意图
在这里插入图片描述
总结:为了提升JVM性能和减少内存开销,避免字符的重复创建 。项目中尽量不要使用new String去创建字符串,最好使用String直接赋值。

1.4 字符串拼接

  • 常量与常量的拼接结果在常量池中。(注意:常量池中不会存在相同内容的常量)
  • 只要拼接内容存在变量,那么拼接后的新变量会在堆内存中新建一个对象实体
  • 如果拼接的结果调用intern()方法,则返回值在常量池中
String s1 = "abc";
String s2 = "def";
String s3 = "abcdef";
String s4 = "abc" + "def";
String s5 = s1 + "def";
String s6 = "abc" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s7);//false
System.out.println(s5 == s6);//false
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false

String s8 = s6.intern();//返回值得到的s8使用的常量池中已经存在的“abcdef”
System.out.println(s3 == s8);//true

//易错
final String str1="abc";
String str2="abcdef";
String str3=str1+"def";
System.out.println(str3 == str2);//true
因为str1声明为final 表示为常量,则str3=str1+"def"是常量与常量的拼接,结果仍在常量池中

2.String类常用函数

2.1 常用函数

int length() 返回字符串的长度

int compareTo(String anotherString) 比较两个字符串的大小
//注:相比较的String位数相等则返回askII码差值。相比较的String位数不等则返回位数差值

int indexOf(String str) 返回指定子字符串在此字符串中第一次出现处的索引

int indexOf(String str, int fromIndex) 返回从指定的索引开始,指定子字符串在此字符串中第一次出现处的索引

int lastIndexOf(String str) 返回指定子字符串在此字符串中最后一次出现处的索引

int lastIndexOf(String str, int fromIndex) 从指定索引开始反向搜索,返回指定子字符串在此字符串中最后一次出现处的索引

// 注:indexOf和lastIndexOf方法如果未找到都是返回-1


char charAt(int index) 返回索引处字符

boolean isEmpty() 判断是否为空串

boolean equals(Object obj) 比较字符串内容是否相同

boolean equalsIgnoreCase(String anotherString) 忽略大小写后比较字符串内容是否相同

boolean endsWith(String suffix) 判断此字符串是否以指定后缀结束

boolean startsWith(String prefix) 判断此字符串是否以指定的前缀开始

boolean startsWith(String prefix, int toffset) 判断此字符串从指定索引开始的子字符串是否以指定前缀开始

boolean contains(CharSequence s) 判断此字符串是否包含指定的 char值序列

boolean matches(String regex) 判断此字符串是否匹配给定的正则表达式

String toLowerCase() 将 String 中的所有字符转换为小写

String toUpperCase() 将 String 中的所有字符转换为大写

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

String concat(String str) 将指定字符串连接到此字符串的结尾

String substring(int beginIndex) 返回从beginIndex开始截取到结尾的子字符串

String substring(int beginIndex, int endIndex) 返回从beginIndex开始截取到endIndex(不包含)的子字符串

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[] split(String regex) 根据给定正则表达式的匹配拆分此字符串。

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

2.2 字符串与字符数组、字节数组的相互转换

1. String ---> char[ ]
   char[] toCharArray()

2.char[ ] ---> String
构造函数:String(char[])
         String(char[],offset,count) 
静态方法:static String copyValueOf(char[] data)
         static String copyValueOf(char[] data,int offset,int count)
         static string valueOf(char[] data)
         
3. String ---> byte[ ]
   byte[] getBytes()
   
4.byte[ ] ---> String
构造函数:String(byte[]) 
         String(byte[],offset,count) 

猜你喜欢

转载自blog.csdn.net/weixin_43956248/article/details/113424407
今日推荐