java中的String

java中String类型

1. JVM(内存图)

要明白java中的String类型的存储,首先要搞清楚JVM的内部

  1. 方法区(主要用于存放方法)
  • 类常量池
  • 静态常量池
  • 字符串常量池(避免频繁的创建和销毁字符串,实现了数据的共享,提高了系统的性能)
  1. 栈区
  2. 堆区
  3. 程序计数区
  4. 本地方法栈

2. 创建一个字符串

public class Main{
 public static void main(String[] args){
     String s1 = "abc";
 }
}

首先在JVM中运行main方法,在栈区中为main方法开辟一块内存,然后在main方法的内存中创建了一个String类型的变量,此时,在方法区中的字符串常量池中就会构造一个"abc" 的字符串,并将该字符串的地址交给String类型的变量

public class Main{
 public static void main(String[] args){
     String s1 = new String("abc");
 }
}

这样就会在堆区中开辟一块内存,然后将地址存储在s1中,但实际上堆中开辟的那个块内存,引用了常量池中的abc

String s1 = new String("abc");

所以说上面这就话在内存中开辟了两块或者三块的内存(如果常量池中有就是两块,如果常量池中没有就在常量池中也开辟一块空间,所以是三块)

3. 字符串的比较

public class Main{
 public static void main(String[] args){
     String s1 = "abc";
     String s2 = "abc";
     String s3 = new String("abc");
     System.out.println(s1 == s2);
     System.out.println(s1 == s3);
 }
}

输出结果:

true
false

等于号在java中默认比较的是地址,s1和s2都是指向字符串常量池中创建的字符串,所以地址相等,所以s1等于s2

但是对于s3而言,new了一个新的对象,该对象指向了字符串常量池中的字符串,所以s1不等于s3

public class Main{
 public static void main(String[] args){
     String s1 = "123";
     String s2 = "456";
     String s3 = s1+s2;

     String s4 = "123456";
     String s5 = "123"+"456";
     System.out.println(s3 == s4);
     System.out.println(s4 == s5)
 }
}

对于字符串s1和s2的拼接,实际上是调用了java中String类中的StringBulder.toString();实际上也就是new了一个新的字符串,所以地址不一样,

但是对于s5中的拼接,会在编译的时候直接常量合并,所以说可以直接将s4和s5看成一样的

false
true

4. 字符串常用方法

String s = "abc";
System.out.println(s.length()); // 获取字符串长度
System.out.println(s.charAt(1)); // 获取字符串指定字符的值,下标从0开始
System.out.println(s.codePointAt(1)); // 获得字符串指定字符的值对应的编码值,下标从零开始,与上面一个类似
System.out.println(s.equals("abc")); // 比较字符串的内容
System.out.println(s.substring(0,3)); // 该字符串的从2到第二个字符 即:[0, 3)
System.out.println(s.indexOf("a")); // 查找某个字符串所在的位置,也可以是一个字符串,也可以跳过多少个字符开始寻找,如果不存在,返回-1
System.out.println(s.lastIndexOf("a")); // 与上面的方法类似,不过是从结尾开始寻找
System.out.println(s.startsWith("a")); // 是否是以a开头的字符串
System.out.println(s.endsWith("c")); // 是否是以c结尾
System.out.println(s.contains("b")); // 是否包含b字符
System.out.println(s.replace("a","c")); // 将字符a替换成字符c
System.out.println(s.toUpperCase()); // 将字符转化成大写
System.out.println(s.toLowerCase()); // 将字符转化成小写
System.out.println(s.trim()); // 将字符串中的开头结尾中的空格去掉

5. 可变字符串(频繁修改时使用)

1. StringBuilder(线程不安全)

2. StringBuffer(线程安全)

进程:计算机中最小的资源分配单位

线程:计算机中最小的执行单位

3. 常用的Api

StringBuilder sb = new StringBuilder("abcdef");
System.out.println(sb.append("a")); // 在sb中添加一个字符或一个字符串
System.out.println(sb.insert(1, "ab")); // 在sb中指定位置插入
System.out.println(sb.delete(2, 3)); // 删除sb中指定位置的字符[2, 3)
System.out.println(sb.deleteCharAt(3)); // 删除指定位置上的字符
sb.setCharAt(2, 'a'); // 修改制定位置上的字符
System.out.println(sb.reverse()); // 字符串反转
posted @   ning12  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示