首页 > 编程语言 >Java基础-String、StringBuffer、StringBuilder类

Java基础-String、StringBuffer、StringBuilder类

时间:2022-12-05 13:23:44浏览次数:36  
标签:Java String int StringBuilder System char println new

String类

String的特性:

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

  • String 是一个 final 类,代表 不 可变的 字符序列 。

  • 字符串 是 常量 ,用双引号引起来表示。 它们 的值在创建之后不能更改 。

  • String 对象的字符内容是存储在一个字符 数组 value[] 中 的。

  • String实现了Serializable接口:表示字符串是支持序列化的。

    ​ 实现了Comparable接口:表示String可以比较大小

  • String:代表不可变的字符序列。简称:不可变性。

    ​ 体现:1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。

    ​ 2. 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。

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

  • 字符串常量池中是不会存储相同内容的字符串的。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    @Stable
    private final byte[] value;
String s1 = "abc";//字面量的定义方式
String s2 = "abc";
s1 = "hello";
image-20221205101411120

String的实例化方式:

  • 方式一:通过字面量定义的方式

  • 方式二:通过new + 构造器的方式

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

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

//通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
//通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。
String s3 = new String("javaEE");
String s4 = new String("javaEE");

System.out.println(s1 == s2);//true
System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false
image-20221205103633581

问题 String str1 = "abc" String str2 = new String("abc") 的区别?

字符串常量存储在字符串常量池中,目的是共享。

字符串非常量对象存储在堆中。

image-20221205104241597

字符串对象是如何存储的:

首先会通过 new 在堆空间中开辟一个空间,返回该地址,但对象中value的地址指向常量池中的数据。因此会在内存中创建两个对象。

String s1 = "javaEE";
String s2 = "javaEE";
String s3 = new String("javaEE");
String s4 = new String("javaEE");
image-20221205104951683
Person p1 = new Person("Tom",12);
Person p2 = new Person("Tom",12);
System.out.println(p1.name == p2.name);//true
image-20221205105131006

字符串常量和字符串变量对象的拼接

  • 常量与常量的拼接结果在常量池 。 且常量池中不会存在相同内容的常量 。
  • 只要其中有一个是变量 ,结果就在堆中。
  • 如果拼接的结果调用 intern() 方法,返回值 就 在常量池中。
String s1 = "hello";
String s2 = "world";

String s3 = "hello" + "world";
String s4 = s1 + "world";
String s5 = s1 + s2;
String s6 = (s1 + s2).intern();

System.out.println(s3 == s4);//false
System.out.println(s3 == s5);//false
System.out.println(s4 == s5);//false
System.out.println(s3 == s6);//true
image-20221205110021650

String常用方法

image-20221205110643015 image-20221205110709615 image-20221205110721613

String与基本数据类型转换

  • 字符串 -> 基本数据类型、包装类

    Integer 包装类的 public static int parseInt (String s):可以将由“数字”字符组成的字符串转换为整型。

    类似地 使用 java.lang 包中的 Byte 、 Short 、 Long 、 Float 、 Double 类调相应的类方法。

  • 基本数据类型、包装类 -> 字符串

    调用 String 类的 public String valueOf int n) 可将 int 型转换为字符串

    相应的 valueOf (byte 、 valueOf (long 、 valueOf (float 、 valueOf (double d) 、 valueOf boolean b) 可由参数的 相应 类型到 字符串的转换

String str1 = "123";
//int num = (int)str1;//错误的
int num = Integer.parseInt(str1);

String str2 = String.valueOf(num);//"123"
String str3 = num + "";

System.out.println(str1 == str3);

String 与 char[]之间的转换

  • String --> char[]:调用String的toCharArray()
  • char[] --> String:调用String的构造器
 String str1 = "abc123"; 

char[] charArray = str1.toCharArray();
for (int i = 0; i < charArray.length; i++) {
    System.out.println(charArray[i]);
}

char[] arr = new char[]{'h','e','l','l','o'};
String str2 = new String(arr);
System.out.println(str2);

String 与 byte[]之间的转换

  • 编码:String --> byte[]:调用String的getBytes()
  • 解码:byte[] --> String:调用String的构造器

编码:字符串 -->字节 (看得懂 --->看不懂的二进制数据)

解码:编码的逆过程,字节 --> 字符串 (看不懂的二进制数据 ---> 看得懂)

说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。

String str1 = "abc123中国";
byte[] bytes = str1.getBytes();//使用默认的字符集,进行编码。
System.out.println(Arrays.toString(bytes));

byte[] gbks = str1.getBytes("gbk");//使用gbk字符集进行编码。
System.out.println(Arrays.toString(gbks));

System.out.println("******************");

String str2 = new String(bytes);//使用默认的字符集,进行解码。
System.out.println(str2);

String str3 = new String(gbks);
System.out.println(str3);//出现乱码。原因:编码集和解码集不一致!


String str4 = new String(gbks, "gbk");
System.out.println(str4);//没有出现乱码。原因:编码集和解码集一致!

StringBuffer和StringBuilder类

String、StringBuffer 和 StringBuilder三者的异同?

String:不可变的字符序列。底层使用char[] 数组进行存储。

StringBuffer:可变的字符序列;线程安全的,效率低。底层使用char[] 数组进行存储。

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

源码分析:

//String
String str = new String();//char[] value = new char[0];
String str1 = new String("abc");//char[] value = new char[]{'a','b','c'};

//StringBuffer
StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组。
System.out.println(sb1.length());// 0 
sb1.append('a');//value[0] = 'a';
sb1.append('b');//value[1] = 'b';

StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16];

问题1 : System.out.println(sb2.length()); sb2的长度是多少?

是3,统计的不是数组的长度,而是添加字符的长度。

问题2:扩容问题:如果要添加的数据底层数组盛不下了,就需要扩容底层的数组。

​ 默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组中。

开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)

StringBuffer(StringBuilder)常用方法

StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
StringBuffer delete(int start,int end):删除指定位置的内容
StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
StringBuffer insert(int offset, xxx):在指定位置插入xxx
StringBuffer reverse() :把当前字符序列逆转
//以上方法支持方法链操作                                                     
//方法链的原理:
public StringBuilder append(StringBuffer sb) {
      super.append(sb);
      return this;
  }                                                     
public int indexOf(String str):返回str在字符串中首次出现的位置
public String substring(int start,int end):返回一个从start开始到end索引结束的左闭右开区间的子字符串
public int length():返回字符串的长度
public char charAt(int n ):取指定位置的字符
public void setCharAt(int n ,char ch):将指定位置的字符改成新的。

总结:

  • 增:append(xxx)
  • 删:delete(int start,int end)
  • 改:setCharAt(int n ,char ch) / replace(int start, int end, String str)
  • 查:charAt(int n )
  • 插:insert(int offset, xxx)
  • 长度:length();
  • 遍历:for() + charAt() / toString()

对比String、StringBuffer、StringBuilder三者的效率:

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

标签:Java,String,int,StringBuilder,System,char,println,new
From: https://www.cnblogs.com/tiancn/p/16952011.html

相关文章

  • java 7中再谈try catch
    java7中的trycatch除了之前谈到的新特性外,本文简单来例子小结下,其实还是有不少地方要注意的,首先看一个典型的代码:先来两个异常类:1.publicc......
  • java中对象存在形式
    本文主要讲述jvm中对象的存储形式:classCat{Stringname;intage;Stringcolor;//行为}依据Cat类创建对象publicclassObject01......
  • JAVASCRIPT数组小结
    ​数组是值的有序集合。每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。JavaScript数组是无类型的,数组元素可以是任意类型,并......
  • 笔记:正确得使用java 8得optional
    publicstaticStringgetName(Useru){if(u==null)return"Unknown";returnu.name;}比如以前这样得代码,经常要判断是否NULL,很麻烦,有了java8得option......
  • JDK的dt.jar和Java BeanInfo接口
    在JAVA_HOME/lib下面有两个比较重要的jar文件,tools.jar和dt.jar。 tools.jar在上篇文章中做了简单的介绍。这里来介绍下dt.jar。在Oracle官方网站搜dt.jar,找到JDKand......
  • (笔记)JMH基准测试,不错的JAVA基准测试工具
    测试JAVA中的方法的执行性能,比较稳妥合理的方法,是用JMH(​​https://openjdk.java.net/projects/code-tools/jmh/​​)这个JAVA的测试工具。1)MAVEN加入库: <properties>......
  • 快速比较JAVA中两个集合是否相等
    有几个方法:1)如果是不在乎顺序,只要内容相同就可以认为相等,则:public<TextendsComparable<T>>booleanisEquals(List<T>list1,List<T>list2){if(list1==nul......
  • Java同步器之ReentrantLock源码分析(一)
    一、概述ReentrantLock是Java并发包中提供的一个可重入的互斥锁。ReentrantLock和synchronized在基本用法,行为语义上都是类似的,同样都具有可重入性。只不过相比原生的Sync......
  • 两道面试题,带你解析Java类加载机制
    在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题:classGrandpa{static{System.out.println("爷爷在静态代码块");}}classFatherextendsGra......
  • JAVA 解压缩代码写法
    packagecom.chinaunicom.asset.common.utils.compress;importlombok.extern.slf4j.Slf4j;importorg.apache.commons.compress.archivers.ArchiveEntry;importorg.......