Java详细分析String类与StringBuffer和StringBuilder的使用方法

作者:洛语言 时间:2022-04-23 15:23:30 

String类基本概念

  • String类属于引用数据类型,不属于基本数据类型。

  • 在Java中只要是" "(双引号)中的,都是String对象。

  • java中规定,双引号中的字符串是不可变的,也就是说"abc"自出生到死亡都不可能变成"abcd",也不能变成"ab"。

  • 在JDK中双引号括起来的字符串都是存储在方法区的字符串常量池当中的。(因为在实际开发中,字符串的使用频率十分高,为了执行效率,就把字符串放在了方法区中的字符串常量池当中)

String字符串的存储原理

  • 通过 String s = “abc” 这种方式,会在方法区中的字符串常量池创建对象,s会保存该字符串在字符串常量池中的地址。

  • 通过 String s = new String(“abc”)的方式创建对象,首先会在字符串常量池中创建"abc"对象(如果字符串常量池中已经有了"abc"则不会再次创建),然后会在堆区创建String类对象,它会储存" abc "在方法区中的地址,s又会保存堆中String对象的地址。

看以下代码:

public class StringTest01 {
   //这两行代码表示创建3个字符串对象,且都在字符串常量池中
   String A = "abc";
   String B = "abc" + "de";
   //通过 new 来创建字符串对象,会先在字符串常量池中寻找"abc"
   //找不到的话就会在字符串常量池中创建一个"abc"对象
   //在堆中创建创建字符串对象,并且保存"abc"在字符串常量池中的地址
   String C = new String("abc");
}

按照以上代码画出JVM内存简图如下:

Java详细分析String类与StringBuffer和StringBuilder的使用方法

知道了String类字符串的存储原理之后,就可以很容易知道以下代码的编译结果:

public class StringTest01 {
   public static void main(String[] args) {
       //没有在堆中创建对象
       //s1与s2都存的是"hello"在字符串常量池中的地址
       String s1 = "hello";
       String s2 = "hello";
       //在堆中创建了对象
       //m,n分别存的是他们在堆中对象的地址
       String m = new String("你好!");
       String n = new String("你好!");
       System.out.println(s1 == s2);//结果为true
       System.out.println(m == n);//结果为false
   }
}

String类的常用构造方法

//String类构造方法的使用
public class StringTest02 {
   public static void main(String[] args) {
       byte []x1 = { 97 , 98 , 99 };
       char []x2 = {'我','是','中','国','人'};
       //String s = new String(byte数组);
       String y1 = new String(x1);
       System.out.println(y1);//ABC
       //String s = new String(byte数组,偏移量,长度)
       String y2  = new String(x1,1,2);
       System.out.println(y2);//BC
       //String s = new String(char数组)
       String y3 = new String(x2);
       System.out.println(y3);//我是中国人
       //String s = new String(char数组,偏移量,长度)
       String y4 = new String(x2,2,3);
       System.out.println(y4);//中国人
   }
}

String类中常用方法

public class StringTest03 {
   public static void main(String[] args) {
       //public char charAt(int index)方法
       //返回索引值处的char类型字符
       char s1 = "中国人".charAt(1);
       System.out.println(s1);//国
       //public int compareTo(String anotherString)方法
       //按字典序比较两个字符串
       System.out.println("abc".compareTo("abd"));//负整数
       System.out.println("abc".compareTo("abc"));//0
       System.out.println("abc".compareTo("abb"));//正整数
       //public boolean contains(CharSequence s)方法
       //判断字符串是否包含s
       System.out.println("abcdefg".contains("efg"));//true
       System.out.println("abcdefg".contains("hij"));//false
       //public boolean endsWith(String suffix)方法
       //判断字符串是否以suffix结尾
       System.out.println("abcde".endsWith("cde"));//true
       System.out.println("abcde".endsWith("qwe"));//false
       //public boolean equalsIgnoreCase(String anotherString) 方法
       //判断两个字符串是否相等,忽略大小写
       System.out.println("ABcd".equalsIgnoreCase("abCD"));//true
       //public byte[] getBytes()
       //将字符串转换成byte数组,并返回
       byte [] s2 = "abcdefg".getBytes();
       for (int i = 0; i < s2.length; i++) {
           System.out.print(s2[i] + " ");
       }//97 98 99 100 101 102 103
       //public int indexOf(String str)
       //判断某个子字符串在当前字符串中第一次出现处的索引
       //若子字符串不存在,返回-1
       System.out.println("abcdefghigk".indexOf("hig"));//7
       System.out.println("abc".indexOf("fgh"));//-1
       //public int lastIndexOf(String str)
       //判断某个子字符串最后一次出现在当前字符串中的索引
       System.out.println("abcdhdhdabc".lastIndexOf("abc"));//8
       //public boolean isEmpty()
       //判断字符串是否为空串
       //底层调用length()方法,空串长度为0
       //注意:判断数组长度是length属性,判断字符串长度是length()方法
       System.out.println("".isEmpty());//true
       //public String replace(char oldChar,char newChar)
       //返回一个将原字符串中所有的oldChar替换为newChar的新字符串,不改变原字符串
       String s3 = "aaatttooo";
       System.out.println( s3.replace('t','q'));//aaaqqqooo
       //public String replace(CharSequence target,CharSequence replacement)
       //CharSequence可以看出String
       //将原字符串中的 target 全部换成 replacement
       String s4 = "abcsgdjsssjabcjdjjdjabc";
       System.out.println(s4.replace("abc","www"));//wwwsgdjsssjwwwjdjjdjwww
       //public String[] split(String regex)
       //以regex为分界线,将字符串分割保存在一个字符串数组当中,并返回
       String s5 = "2022-3-19";
       String [] str = s5.split("-");
       System.out.println(str[0] + str[1] + str[2]);//2022319
       //public String substring(int beginIndex)
       //返回一个以索引beginIndex开始直至结尾的字符串
       System.out.println("abcdefgh".substring(4));//efgh
       //public String substring(int beginIndex,int endIndex)
       //返回一个以索引值beginIndex开始,以索引值endIndex结束(不包含该索引值处的字符)的子字符串
       System.out.println("abcdefgh".substring(2,5));//cde
       //public char[] toCharArray()
       //将一个字符串以字符数组的形式返回
       char[] str2 = "abcdefg".toCharArray();
       for(int i = 0 ; i < str2.length ; i++){
           System.out.println(str2[i]);
       }
       //public String toLowerCase()
       //返回一个将原字符串中所有字符变成小写的新字符串
       System.out.println("ABcDeFG".toLowerCase());//abcdefg
       //public String toUpperCase()
       //返回一个将原字符串中所有字符变成大写的新字符串
       System.out.println("aCbcdEfg".toUpperCase());//ABCDEFG
       //public String trim()
       // 返回一个去除字符串的前后空白(空格)的新字符串
       System.out.println("       abcdefg      ".trim());//abcdefg
       //public static String valueOf(参数列表)
       //参数列表可以是int型,char型,int数组,对象 等等.......
       //String类中唯一一个静态方法,可以直接调用
       //将非字符串转换为字符串
       //println()底层调用的就是valueOf()方法,只要是打印在控制台上的都是字符串
       System.out.println(String.valueOf(true));
   }
}

StringBuffer类

思考:

  • 频繁使用字符串拼接会有什么影响?

  • java中字符串是不可变的,每拼接一次都会产生一个新的字符串

  • 字符串是存在字符串常量池中的,频繁使用字符串拼接会占用大量的方法区空间

为了避免以上问题我们就可以使用到StringBuffer类

//java.lang.StringBuffer
public class StringBufferTest {
   public static void main(String[] args) {
       //创建一个初始化容量为16个 byte[] 数组(字符串缓冲区对象)
       StringBuffer strBuffer = new StringBuffer();
       //拼接字符串调用 append()方法
       //append()方法底层会调用 System.arraycopy()方法,效率较低
       //append()再追加时,如果byte[]满了之后会自动扩容
       strBuffer.append(1);
       strBuffer.append('q');
       strBuffer.append(3.14);
       strBuffer.append("abc");
       System.out.println(strBuffer);//1q3.14abc
       //StringBuffer可以进行一定的优化
       //在创建StringBuffer时尽可能可能给定一个合适的初始化容量
       //从而减少底层数组的扩容次数
       //指定初始化容量的字符串缓冲区
       StringBuffer newstrBuffer = new StringBuffer(100);
   }
}

StringBuilder类

它的用法与StringBuffer十分相似,但是也有很大的区别:

  • StringBuffer中的方法都有synchronized关键字修饰,表示StringBuffer在多线程编译环境下是安全的

  • StringBuilder中方法没有synchronized关键字修饰,表示StringBuilder在多线程编译环境下是不安全的

来源:https://blog.csdn.net/m0_62969222/article/details/123616761

标签:Java,String,StringBuffer,StringBuilder
0
投稿

猜你喜欢

  • JavaWeb登录界面登录失败在同一页面进行提示的解决

    2023-11-26 15:51:34
  • SpringBoot跨域Access-Control-Allow-Origin实现解析

    2023-11-28 23:04:34
  • jsp+servlet实现简单登录页面功能(附demo)

    2023-09-24 11:32:28
  • java算法之Math.random()随机概率玩法实例演示

    2023-11-28 23:32:17
  • java随机生成8位数授权码的实例

    2022-04-24 12:03:47
  • 详解Spring Boot Security工作流程

    2023-12-17 12:23:52
  • SpringBoot中多环境配置和@Profile注解示例详解

    2023-11-29 05:39:04
  • 使用jenkins部署springboot项目的方法步骤

    2022-06-05 05:18:31
  • 微信小程序获取手机号,后端JAVA解密流程代码

    2023-11-29 07:57:26
  • Java经典面试题最全汇总208道(五)

    2023-11-10 07:06:46
  • Java 分割字符串详解及实例代码

    2023-11-29 13:18:42
  • Java实现提取QSV文件视频内容

    2023-08-24 13:33:45
  • mybatis源码解读之executor包懒加载功能 

    2022-09-17 00:28:05
  • Java基础将Bean属性值放入Map中的实例

    2023-10-11 13:57:40
  • SpringBoot 返回Json实体类属性大小写的解决

    2023-08-05 12:30:49
  • spring boot thymeleaf 图片上传web项目根目录操作步骤

    2023-11-23 10:50:46
  • 一文带你搞懂Redis分布式锁

    2021-09-26 12:56:14
  • JAVA中Comparable接口和自定义比较器示例讲解

    2023-11-20 22:16:32
  • Java Swing实现让窗体居中显示的方法示例

    2023-11-06 02:59:07
  • IDEA 2020.3最新永久激活码(免费激活到 2099 年,亲测有效)

    2023-07-14 05:37:43
  • asp之家 软件编程 m.aspxhome.com