java.lang.String类

概述

String:代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现

  • String声明为final,不可被继承
  • 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
  • String实现了Serializable接口:表示字符串是支持序列化的。
  • 实现了Comparable接口:表示String可以比较大小
  • String内部定义了private final char[] value用于存储字符串数据
  • 通过字面量的方式(区别于用new String()给字符串赋值),此时的字符串值声明在字符串常量池中)。
  • 字符串常量池中是不会存储相同内容(使用String类的equals()比较)的字符串的。
  1. public final class String
  2. implements java.io.Serializable, Comparable<String>, CharSequence {
  3. /** The value is used for character storage. */
  4. private final char value[];
  5. /** Cache the hash code for the string */
  6. private int hash; // Default to 0

String的不可变 性

  1. 当对字符串重新赋值时,需要重新指定内存区域赋值
  2. 当对现在的字符串进行连接操作时,也需要重新指定内存区域赋值
  3. 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。

总结就是只要字符串值有更改,都需要重新指定内存区域赋值。若新值在内存区域已存在,则直接指向该区域,若没有则重新开辟空间

String对象的创建

建议去看API,以下展示集几种常用的

  1. //字面量方式
  2. String str = "hello";
  3. //本质上this.value = new char[0];
  4. String s1 = new String();
  5. //this.value = s.value;
  6. String s2 = new String(String s);
  7. //this.value = Arrays.copyOf(value, value.length);
  8. String s3 = new String(char[] a);
  9. //从字符数组a的startIndex位置截取count个字符
  10. String s4 = new String(char[] a,int startIndex,int count);

从上面代码可以看出String实例化主要有两种方式

  • 方式一:通过字面量定义的方式
  • 方式二:通过new + 构造器的方式
  1. //通过字面量定义的方式:此时的s1和s2的数据声明在方法区中的字符串常量池中。
  2. String s1 = "javaEE";
  3. String s2 = "javaEE";
  4. //通过new + 构造器的方式:此时的s3和s4保存的是地址值,指向堆空间中的数据。
  5. String s3 = new String("javaEE");
  6. String s4 = new String("javaEE");
  7. System.out.println(s1 == s2);//true
  8. System.out.println(s1 == s3);//false
  9. System.out.println(s1 == s4);//false
  10. System.out.println(s3 == s4);//false

面试题

  1. String s = new String("abc");方式创建对象,在内存中创建了几个对象?

    答:两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc"

  2. String str1 = "abc" 与 String str2 = new String("abc");的区别?

  3. 字符串拼接方式赋值的对比

  1. String s1 = "javaEE";
  2. String s2 = "hadoop";
  3. String s3 = "javaEEhadoop";
  4. String s4 = "javaEE" + "hadoop";
  5. String s5 = s1 + "hadoop";
  6. String s6 = "javaEE" + s2;
  7. String s7 = s1 + s2;
  8. String s9 = s1 + s2;
  9. System.out.println(s3 == s4);//true
  10. System.out.println(s3 == s5);//false
  11. System.out.println(s3 == s6);//false
  12. System.out.println(s3 == s7);//false
  13. System.out.println(s5 == s6);//false
  14. System.out.println(s5 == s7);//false
  15. System.out.println(s6 == s7);//false
  16. System.out.println(s7 == s9);//false
  17. String s8 = s6.intern();//返回值得到的s8使用的常量值中已经存在的“javaEEhadoop”
  18. System.out.println(s3 == s8);//true
  19. ****************************
  20. String s1 = "javaEEhadoop";
  21. String s2 = "javaEE";
  22. String s3 = s2 + "hadoop";
  23. System.out.println(s1 == s3);//false
  24. final String s4 = "javaEE";//s4:常量
  25. String s5 = s4 + "hadoop";
  26. System.out.println(s1 == s5);//true
  1. 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
  2. 只要其中一个是变量,结果就在堆中,且不管变量名是否相同开辟的空间都不同。
  3. 如果拼接的结果调用intern()方法,返回值就在常量池中
  4. 若变量用final修饰就变成常量
  1. 下列程序运行结果
  1. public class StringTest {
  2. String str = new String("good");
  3. char[] ch = { 't', 'e', 's', 't' };
  4. public void change(String str, char ch[]) {
  5. str = "test ok";
  6. ch[0] = 'b'; }
  7. public static void main(String[] args) {
  8. StringTest ex = new StringTest();
  9. ex.change(ex.str, ex.ch);
  10. System.out.print(ex.str); //good 不可变性
  11. System.out.println(ex.ch); //best
  12. } }

StringBuffer、StringBuilder

  • StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储
  • StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]

StringBuffer与StringBuilder的内存解析

  1. //以StringBuffer为例:
  2. String str = new String();//char[] value = new char[0];
  3. String str1 = new String("abc");//char[] value = new char[]{'a','b','c'};
  4. StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组。
  5. System.out.println(sb1.length());//0
  6. sb1.append('a');//value[0] = 'a';
  7. sb1.append('b');//value[1] = 'b';
  8. StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16];
  9. System.out.println(sb2.length()); //3

扩容问题

如果要添加的数据长度大于16,那就需要扩容底层的数组。默认情况下,扩容为原来容量的2倍 + 2,同时将原数组中的元素复制到新的数组中。

开发中建议指定长度:StringBuffer(int capacity) 或 StringBuilder(int capacity)

三者的执行效率

从高到低排列:StringBuilder > StringBuffer > String

String、StringBuffer、StringBuilder三者的对比


  1. abstract class AbstractStringBuilder implements Appendable, CharSequence {
  2. char[] value; //value没有final修饰,可以扩容
  3. int count; //count记录有效字符的个数
  4. AbstractStringBuilder() {
  5. }
  6. AbstractStringBuilder(int capacity) {
  7. value = new char[capacity];
  8. }
  • StringBuilder 和 StringBuffer可用方法一致
  • StringBuilder 和 StringBuffer都继承于AbstractStringBuilder
  • StringBuffer之所以是线程安全的,是因为方法用synchronized修饰
  • StringBuilder 和 StringBuffer 支持链式调用

StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器

  1. StringBuffer() //初始容量为16的字符串缓冲区
  2. StringBuffer(int size) //构造指定容量的字符串缓冲区
  3. StringBuffer(String str) //将内容初始化为指定字符串内容

StringBuffer 和 StringBuilder的常用方法

  1. StringBufferappend(xxx) //提供了很多的append()方法,用于进行字符串拼接
  2. StringBufferdelete(int start,int end) //删除指定位置的内容
  3. StringBufferreplace(intstart,intend,Stringstr) //把[start,end)位置替换为str
  4. StringBufferinsert(int offset,xxx) //在指定位置插入xxx
  5. StringBufferreverse() //把当前字符序列逆转

【Java】String、StringBuffer、StringBuilder的更多相关文章

  1. 【37】String,StringBuffer,StringBuilder区别和概念

    基本的概念: 查看 API 会发现,String.StringBuffer.StringBuilder 都实现了 CharSequence 接口,内部都是用一个char数组实现,虽然它们都与字符串相关 ...

  2. 【Java】String和Date、Timestamp之间的转换

    首先,定义一个Format的日期格式: SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 一.S ...

  3. Java学习——String,StringBuffer和StringBuilder

    Java学习——String,StringBuffer和StringBuilder 摘要:本文主要介绍了String字符串在内存中的存储情况,以及StringBuffer和StringBuilder的 ...

  4. 认识Java中String与StringBuffer以及StringBuilder

    String(引用数据类型) String对象一经创建就不会发生变化(在常量池里),即便是赋予新的值,也不是在原来的基础上改变,而是创建一个新的字符串对象,将引用指向这个对象,会造成空间的浪费: St ...

  5. 【Java】String、StringBuilder和StringBuffer

    [String] 首先,从String类的定义入手,可以看到String类是由final修饰,即不可变的,一旦创建出来就不可修改,因此首先明确,字符串的拼接.截取等操作都会产生新的字符串对象. 观察以 ...

  6. 【java】学习路径17-StringBuffer、StringBuilder的使用与区别

    本文讲解StringBuffer和StringBuilder的使用与区别. 1-- String String类型我们已经很熟悉了,String一旦被赋值,其在堆中的数据便无法修改. 平时我们的&qu ...

  7. 【Java】运算符(算术、赋值、比较(关系)、逻辑、条件、位运算符)

    运算符 文章目录 运算符 1. 算术运算符 2. 赋值运算符 3. 比较运算符 4. 逻辑运算符 5. 条件运算符 6. 位运算符 7. 运算符优先级 8. 运算符操作数类型说明 9.code 算术运 ...

  8. 【java】String类和StringBuffer类常用操作

    String类是字符串常量,是不可更改的常量.而StringBuffer是字符串变量,它的对象是可以扩充和修改的.StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于Stri ...

  9. 【java】String类常见操作

    秋招做题需要,总结String类常用api如下: 简单的:str.length().str.isEmpty().str.split(“;”)切割 1.字符串反转:借助StringBuilder/Str ...

随机推荐

  1. 试玩Aid Learning

    前言 记录一下步骤 下载安装 github官网 切换源 ## 打开Terminal复制回车即可 cd /etc/apt/&& cp sources.list sources.list. ...

  2. [转载]session多服务器共享的方案梳理

    转载网址: http://www.cnblogs.com/wangtao_20/archive/2013/10/29/3395518.html session的存储了解以前是怎么做的,搞清楚了来龙去脉 ...

  3. 关于python中的可哈希与不可哈希

    可哈希:简要的说可哈希的数据类型,即不可变的数据结构(字符串str.元组tuple.对象集objects).它是一个将大体量数据转化为很小数据的过程,甚至可以仅仅是一个数字,以便我们可以用在固定的时间 ...

  4. english note(6.17to6.23)

    6.17 http://www.51voa.com/VOA_Special_English/are-these-us-treasures-about-to-be-destroyed-82260_1.h ...

  5. P5305-[GXOI/GZOI2019]旧词【树链剖分,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P5305 题目大意 给一棵有根树和\(k\),\(Q\)次询问给出\(x,y\)求 \[\sum_{i=1}^{x} ...

  6. Android12系统源码分析:NativeTombstoneManager

    Android12系统源码分析:NativeTombstoneManager 概述 android12新增的system_server进程(LocalService)本地服务,用于管理native t ...

  7. Python技法2:函数参数的进阶用法

    1.关键字参数(positional argument)和位置参数(keyword argument) Python函数的参数根据函数在调用时(注意,不是函数定义时)传参的形式分为关键字参数和位置参数 ...

  8. Java语言程序设计与数据结构(基础篇)第七章答案

    答案为本人求解,如有错误,还望海涵.如有雷同,纯属巧合. 7.1 import java.util.Scanner; public class Main { public static void ma ...

  9. noip2017D1T3逛公园(拓扑图上dp,记忆化搜索)

    QWQ前几天才刚刚把这个D1T3写完 看着题解理解了很久,果然我还是太菜了QAQ 题目大意就是 给你一个n个点,m条边的图,保证1能到达n,求从1到n的 (设1到n的最短路长度是d)路径长度在[d,d ...

  10. WIFI Deauth攻击-爬坑笔记

    这里用Aircrack这款工具进行介绍: 准备工作:无线网卡连接电脑或者虚拟机(免驱的最好),如需驱动请自行安装驱动 1.将无线网卡接入测试电脑Linux虚拟机(装有Aircrack-ng) 2.测试 ...