String类

一、String类的理解和创建对象

  1. String对象用于保存字符串的,也就是一组字符序列
  2. 字符常量对象是用双引号括起来的字符序列。
  3. 字符串的字符使用Unicode字符编码,一个字符(不区分字符还是汉字)占两个字节
  4. String类常用构造器

String s2 = new String(String original);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count)
String s5 = new String(byte[] b)
  1. String 实现了 接口Serializable 【String可以串型化,可以在网络传输】

    • 接口Comparable 【String可以相互比较大小】
  2. String 是一个finally类,不能被其他类继承

  3. String 有属性 private final byte[] value; 用于存放字符串内容

    • 即:String本质是一个value数组,且这个数组的地址不能被改变

      但是它里面存的字符可以改变

  4. 这个value是一个final类型的,不可修改的(指的是一地址不可修改)

    • 即value不能指向新的地址,但是字符的内容可以变化
     final char[] value = {'a','b','c'};
    char[] v2 = {'t','o','m'};
    // value =v2;//不可以修改value的地址
    // Cannot assign a value to final variable 'value'
    value[0] = 'H';

String关系图:


二、String类创建的方式

1)方式一:直接赋值String s = "ywl"

2)方式二:调用构造器String s = new String("ywl");

两种创建String对象的区别

  1. 方式一:先从常量池查看是否有"ywl"数据空间,如果有,直接指向;如果没有则重新创建,然后指向。S最终指向的是常量池的空间地址
  2. 方式二:先在堆中创建空间,里面有了value属性,指向常量池的ywl空间,如果没有则在常量次中创建'ywl'并让value指向这个地址,如果有,让value属性指向现有的字符串的地址.

画出两种方式的内存分布图

测试题

题目1:

知识点:

  • 当调用intern方法时,如果池已经包含与equals(Object)方法确定的相当于此String对象的字符串,则返回来自池的字符串。否则,此String对象将添加到池中,并返回对此String对象的引用。

解读:

  • b.intern()方法最终返回的常量池的地址(对象)

题目二:

注意:

  • 编译器在底层会做一个优化,判断创建的常量池对象,是否有引用指向,如果没有,则直接拼接到一起
  • String是一个final类,代表不可变的字符序列
  • 字符串是不可变的,一个字符串对象一旦被分配,其内容是不可变的

题目三:

public static void main(String[] args) {
String a = "hello";
String b = "abc";
//1.先创建一个 StringBuilder sb = StringBuilder()
//2.执行 sb.append("hello");
//3. sb.append("abc");
//4. Str c =sb.toString();
String c = a + b;
}
  • String c1 = "ab" + "cd";常量相加,看的是池
  • String c1 = a + b; 变量相加,是在堆中

小结:

  • 底层是StringBuilder sb = new StringBuilder();

    • sb.append(a);
    • sb.append(b);
    • sb是在堆中,并且append是在原来字符串的基础上追加的

题目四:


三、String常用方法

String类是保存字符串常量的。每次更新都需要重新开辟空间,效率较低,因此java设计者还提供了StringBuilder和 StringBuffer来增强String的功能,并提高效率。[后面我们还会详细介绍StringBuilder 和 StringBuffer]

第一组:

 public static void main(String[] args) {
//1.equals比较内容是否相等,区分大小写
String str1 = "hello";
String str2 = "HELLO";
System.out.println(str1.equals(str2));//F //2.equalsIgnoreCase忽略大小写,比较内容是否相等
System.out.println(str1.equalsIgnoreCase(str2));//T //3.length获取字符串的长度
System.out.println(str1.length());//5 //4.indexOf 获取字符在字符串对象中第一次出现的索引,索引从 0 开始,如果找不到,返回-1
// 也可以是字符串
System.out.println("l index=" + str1.indexOf('l')); //5.lastIndexOf 获取字符在字符串中最后一次出现的索引,索引从 0 开始,如果找不到,返回-1,
// 也可以是字符串
System.out.println("l lastIndex=" + str1.lastIndexOf("l")); //6.substring 截取指定范围的子串
String name = "hello,大龙";
System.out.println(name.substring(6));//大龙,从索引6开始截取,截取所有的内容
System.out.println(name.substring(2,5));//hello,从0开始截取,截取到索引 5-1 的位置
}

第二组:

 public static void main(String[] args) {
//1.toUpperCase 转换成大写
String s = "Hello";
System.out.println(s.toUpperCase());//HELLO //2.toLowerCase
System.out.println(s.toLowerCase()); //3.concat拼接字符串
String s1 = "宝玉";
s1 = s1.concat("林黛玉").concat("together");
System.out.println(s1); //4.replace 替换字符串中的字符,返回一个替换后的对象,但s1本身并没有被替换
//将s1中所有的宝玉替换成薛宝钗
String s2;
s2 = s1.replace("宝玉","薛宝钗");
System.out.println(s1);//宝玉林黛玉together
System.out.println(s2);//薛宝钗林黛玉together //5.split 分割字符串, 对于某些分割字符,我们需要 转义比如 | \\
String poem = "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦";
//老韩解读:
// 1. 以 , 为标准对 poem 进行分割 , 返回一个数组
// 2. 在对字符串进行分割时,如果有特殊字符,需要加入 转义符 \ String[] split = poem.split(",");
poem = "E:\\aaa\\bbb";
split = poem.split("\\\\");
System.out.println("==分割后内容===");
for (int i = 0; i < split.length; i++) {
System.out.println(split[i]);
} //7.compareTo 比较两个字符串的大小,如果前者大
// 则返回正数,后者大,则返回负数,如果相等,返回 0
// (1)如果长度相同,内容也相同,返回0
// (2)如果长度相同或者不相同,但是在比较适时,可以区分大小
// 返回的是不同值的差值
// (3)如果字符串长度不一样,其他字符都一样,那么就把用前面字符串的长度减去后面字符串的长度
String a = "jack123";// len = 3
String b = "jack";// len = 4
System.out.println(a.compareTo(b));// 返回值是 'c' - 'a' = 2; String name = "john";
int age = 10 ;
double score = 98.3/3;
char gender = '男';
//将所有的信息都拼接在一个字符串. String info =
String info ="我的姓名是" + name + "年龄是" + age + ",成绩是" + score + "性别是" + gender + "。希望大家喜欢我!";
System.out.println(info); //注意:
// 保留小数位会进行四舍五入
String formatStr ="我的姓名%5s 年龄%3d ,成绩是%.2f,我的性别%2c.希望大家喜欢我";
String info2 =String.format(formatStr,name,age,score,gender);
System.out.println(info2);
}

四、StringBuffer类

java.lang.StringBuffer代码可变的字符序列,可以对字符串内容进行增删。

  • 很多方法与String相同,但是StringBuffer是可变长度的
  • StringBuffer是一个容器

1.String vs StringBuffer

  1. String保存的是字符串常量,里面的值不能更改,每次String类的更新实际上是更改地址,效率比较低

    • private final char value[];,放在常量池中
  2. StringBuffer保存的是字符串变量,里面的值可以更改,每次更新实际上可以更细内容,不用每次更新地址,效率比较高

    • char[] value;,放在堆中

String 和StringBuffer相互转换

package com.hspedu.stringbuff_;

/**
* @author DL5O
* @version 1.0
*/
public class StringAndStringBuffer {
public static void main(String[] args) {
//看 String-->StringBuffer
String str = "hello";
//方式1
// 这里只是把str传入到StringBuffer的构造器中,对原来的str没有影响
StringBuffer stringBuffer = new StringBuffer(str); //方式2
//使用append方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1 = stringBuffer1.append(str); //看看 StringBuffer -> String
StringBuffer stringBuffer3 = new StringBuffer("ywl"); //方式1:使用StringBuffer提供的toString方法
String s = stringBuffer3.toString(); //方式2:使用构造器来搞定
String s1 = new String(stringBuffer3);
}
}

2.StringBuffer的常用方法

  1. 增:append
  2. 删:delete(start,end)
  3. 改:replace(start,end,string)
    • 将start-end间的内容替换掉,不含end
  4. 查:indexOf
    • 查找子串在字符串第1次出现的索引,如果找不到就返回-1
  5. 插:insert
  6. 获取长度:length
package com.hspedu.stringbuff_;

/**
* @author DL5O
* @version 1.0
*/
public class StringBufferMethod01 {
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("hello"); //增
stringBuffer.append(',');//"hello,"
stringBuffer.append("张三丰");//"hello,张三丰"
stringBuffer.append("赵敏").append(100).append(true).append(10.5);
//"hello,张三丰赵敏""
System.out.println(stringBuffer);//hello,张三丰赵敏100true10.5 //删
/*
删除索引>=start && <end 出的字符
解读:删除11~14的字符,但是不包含14
*/
stringBuffer.delete(11,14);//删除100
System.out.println(stringBuffer);//hello,张三丰赵敏true10.5 //改
//使用周芷若替换索引 9~11 的字符,[9,11)
stringBuffer.replace(9,11,"周芷若");
System.out.println(stringBuffer);//hello,张三丰周芷若true10.5 //查找
int indexOf = stringBuffer.indexOf("张三丰");
System.out.println(indexOf);//6
//插入
//老韩解读,在索引为9的位置插入 "赵敏",原来索引为9的内容自动后移
stringBuffer.insert(9,"赵敏");
System.out.println(stringBuffer);//hello,张三丰赵敏周芷若true10.5 System.out.println(stringBuffer.length()); }
}

课堂练习题

package com.hspedu.stringbuff_;

import java.util.Scanner;

/**
* @author DL5O
* @version 1.0
*/
public class StringBufferExercise02 {
public static void main(String[] args) {
/*
输入商品名称和商品价格,要求打印效果示例, 使用前面学习的方法完成:
商品名 商品价
手机 123,564.59 //比如 价格 3,456,789.88
要求:价格的小数点前面每三位用逗号隔开, 思路分析
1.定义一个Scanner类,接受用户的输入
2.使用StringBuffer的insert,需要将String转换成 StringBuffer
3.然后使用相关方法进行字符串的处理
*/
// Scanner sc = new Scanner(System.in);
// System.out.print("请输入商品名:");
// String name = sc.next();
String name = "手机";
// System.out.print("请输入商品价格:");
// String price = sc.next(); String price = "123564123456.69";
StringBuffer sb = new StringBuffer(price);
//先完成最简单的123,564.69
//找到小数点的索引,然后再该位置的前三位插入,号即可 //老师的思路:
for (int index = sb.lastIndexOf(".") -3; index > 0; index -= 3) {
sb = sb.insert(index, ",");
}
System.out.println(sb); //我的思路:
//int index = sb.lastIndexOf(".");
//index为小数点在字符串中的下标,当下标<=0时,代表到了字符串中的第一个位置,
//就添加字符串完毕,结束循环
/* while (true) {
index = index - 3;
if(index <= 0){
break;
}
sb = sb.insert(index, ",");
}
// sb = sb.insert(index - 3, ",");
System.out.println(sb);
*/
}
}

五、StringBuilder类

  1. 一个可变的字符序列。此类提供一个与StringBuffer兼容的API,但不保证同步(StringBuilder 不是线程安全)。

    • 该类被设计用作 StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。如果可能,建议优先采用该类因为在大多数实现中,它比 StringBuffer要快[后面测]。
  2. 在 StringBuilder上的主要操作是append和 insert方法,可重载这些方法,可以接受任意类型的数据。

注意事项

StingBuilder和StringBuffer均代表可变的字符序列,方法是一样的,所以使用和StringBuffer一样

package com.hspedu.stringbuilder_;

/**
* @author DL5O
* @version 1.0
*/
public class StringBuilder01 {
public static void main(String[] args) {
//1.StringBuilder 继承了AbstractStringBuilder 类
//2.实现了Serializable,说明StringBuilder对象是可以串型化的(该对象可以网络传输)
// 也可以保存到文件
//3.StringBuilder 也是个final类,不能被继承
//4.StringBuilder 对象的字符序列仍然是存放在其父类 AbstractStringBuilder的 byte[] value;
// 因此,字符序列是存放在堆中
//5.StringBuilder 的所有方法没有做互斥的处理,即没有synchronized关键字
// 即推荐在单线程的时候使用
StringBuilder stringBuilder = new StringBuilder();
}
}

六、String、StringBufferStringBuilder

  1. StringBuffer和StringBuilder非常相似,他们都代表可变的字符序列,并且方法也一样

  2. String:不可变字符序列,效率低,但是它的复用率高

  3. StringBuffer:可变字符序列,效率高,效率较高(增删改查),线程安全

  4. StringBuilder:可变字符序列,效率最高,线程不安全

  5. String使用注意说明:

    • stirng s = "a";//创建了一个字符串

      s +="b";//实际上原来的"a"字符串对象已经丢弃了,现在又产生了一个字符串s+"b"也就是“ab”

    • 如果多次执行,就会有大量的副本留在常量池中,降低效率,影响程序的性能

    • 故:如果要对String做大量的修改,就不使用String类

总结:

  1. 如果字符串存在大量的修改操作,一般使用 StringBufferStringBuilder

  2. 如果字符串存在大量的修改操作,并在单线程的情况,使用 StringBuilder

  3. 如果字符串存在大量的修改操作,并在多线程的情况,使用 StringBuffer

  4. 如果我们字符串很少修改,被多个对象引用,使用String,比如配置信息等

JAVA String、StringBuilder、和StringBuffer的区别,及如何使用的更多相关文章

  1. String,StringBuilder与StringBuffer的区别

    相信大家看到过很多比较String和StringBuffer区别的文章,也明白这两者的区别,然而自从Java 5.0发布以后,我们的比较列表上将多出一个对象了,这就是StringBuilder类.St ...

  2. String, StringBuilder 与StringBuffer的区别与联系

    1.区别 (1)String构建的对象不能改变,每次对String进行操作时,如两个String相加,需要新建一个String对象,然后容纳最终的结果. 而StringBuilder与StringBu ...

  3. java String,StringBuilder和StringBuffer

    String:1.java语言中的字符串值属于String类,虽然有其它方法表示字符串(如字符数组),但java一般使用Sting类作为字符串的标准格式,java编译器把字符串值作为String对象. ...

  4. StringBuilder和StringBuffer的区别

    Java中StringBuilder和StringBuffer的区别分析 StringBUilder是线程不安全的(线程同步访问的时候会出问题),但是效率相对较高. (String类型使用加号进行拼接 ...

  5. JAVA String介绍、常量池及String、StringBuilder和StringBuffer得区别. 以及8种基本类型的包装类和常量池得简单介绍

    一.概述 String是代表字符串的类,本身是一个最终类,使用final修饰,不能被继承. 二.定义方式   方式一:直接赋值法 String str1 = "hello"; 方式 ...

  6. String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别 (String系列之1)

    本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...

  7. String、StringBuilder和StringBuffer的区别

    1         String.StringBuilder和StringBuffer的区别 String.StringBuilder.StringBuffer都可以用来保存字符串.如果是使用次数比较 ...

  8. String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别

    本章主要介绍String和CharSequence的区别,以及它们的API详细使用方法. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/string01. ...

  9. 面试必知:String、StringBuilder、StringBuffer的区别

    你知道String.StringBuilder.Stringbuffer的区别吗?当你创建字符串的时候,有考虑过该使用哪个吗? 别急,这篇文章带你解决这些问题. 可变性 首先,String是字符串,我 ...

  10. StringBuilder与StringBuffer的区别

    相信大家看到过很多比较String和StringBuffer区别的文章,也明白这两者的区别,然而自从Java 5.0发布以后,我们的比较列表上将多出一个对象了,这就是StringBuilder类.St ...

随机推荐

  1. 在Rainbond中实现数据库结构自动化升级

    Rainbond 这款产品一直致力于打通企业应用交付的全流程,这个流程中不可或缺的一环是企业应用的不断升级.迭代.Rainbond 特有的能力,是可以将囊括多个服务组件的企业应用系统进行打包,并执行一 ...

  2. response.getWriter().write()和 response.getWriter().print()的区别 以及 PrintWriter对象 和 out对象 的区别

    感谢原文作者:krismile__qh 原文链接:https://blog.csdn.net/krismile__qh/article/details/89926001 一.response.getW ...

  3. new操作符具体干了什么呢?

    考察对new关键的深刻认识,是否对前端知识有专研,如果没有专研的人,肯定说创建了一个对象,恭喜你面试官知道你是小菜鸟来的,这次面试基本上没有太大的希望了.一定要对new过程的4个步骤非常清楚,这样才能 ...

  4. JVM学习四:深入分析ClassLoader

    一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...

  5. MSTP多生成树协议

    MSTP多生成树协议 目录 MSTP多生成树协议 1.MSTP(Multiple Spanning Tree Protocol)概述 2.STP.RSTP.PVST的应用缺陷 3.MSTP的主要特点 ...

  6. 【译】System.Text.Json 的下一步是什么

    .NET 5.0 最近发布了,并带来了许多新特性和性能改进.System.Text.Json 也不例外.我们改进了性能和可靠性,并使熟悉 Newtonsoft.Json 的人更容易采用它.在这篇文章中 ...

  7. Vue项目中实现文件下载到本地的功能

    公司业务需求,我需要实现一个合同模板,自定义输入内容后生成合同随后导出下载合同.(自定义部分用到的是) 为了实现这个文件下载到本地的功能,真的是废了九牛二虎之力,以至于差点放弃(主要还是自己菜).刚开 ...

  8. linux_6

    1.编写脚本实现登陆远程主机.(使用expect和shell脚本两种形式). #使用expect远程登录 [root@centos8 ~]#dnf -y install expect [root@ce ...

  9. Springboot+Websocket+JWT实现的即时通讯模块

    场景 目前做了一个接口:邀请用户成为某课程的管理员,于是我感觉有能在用户被邀请之后能有个立马通知他本人的机(类似微博.朋友圈被点赞后就有立马能收到通知一样),于是就闲来没事搞了一套. ​ 涉及技术栈 ...

  10. Solution -「AGC 036D」「AT 5147」Negative Cycle

    \(\mathcal{Descriprtion}\)   Link.   在一个含 \(n\) 个结点的有向图中,存在边 \(\lang i,i+1,0\rang\),它们不能被删除:还有边 \(\l ...