首页 > 其他分享 >String

String

时间:2023-07-15 15:45:21浏览次数:45  
标签:String 对象 池中 str 字符串 常量

String str1= "abc";
String str2= new String("abc");
String str3= str2.intern();
System.out.println(str1==str2);
System.out.println(str2==str3);
System.out.println(str1==str3);

结果

false
false
true

为什么使用byte数组来替换char数组?

一个 char 字符占 16 位,2 个字节。意味着存储占一个字节的字符非常浪费。
为了节约内存,JDK1.9 的 String 类使用了占 8 位1 个字节的 byte 数组来存放字符串。

String不可变

String类被final关键字修饰了,而且变量char数组也被final修饰了。
第一,保证String对象的安全性,避免String对象被恶意修改。
第二,确保hash值的唯一性,使得HashMap等类实现key-value缓存功能。
第三,实现字符串常量池。

Java通常有两种创建字符串对象的方式

1 通过字符串常量的方式创建,如String str=“abc”
JVM首先会检查该对象是否在字符串常量池中,如果在,就返回该对象引用,否则新的字符串将在字符串常量池中被创建。这种方式可以减少同一个值的字符串对象的重复创建,节约内存。

2 字符串变量通过new形式的创建,如String str=new String(“abc”)
在类加载时,“abc"将会在字符串常量池中创建。
在调用new时,JVM调用构造函数,在堆中创建一个String对象,char数组引用字符串常量池中的"abc”字符串。
str指向堆中的String对象。

String对象的优化

如何构建超大字符串?

字符串常量的累计
String str= "ab" + "cd" + "ef";
理论上,首先会生成ab对象,再生成abcd对象,最后生成abcdef对象,
实际上,编译器自动优化这行代码,只有一个对象生成。
String str= "abcdef";

字符串变量的累计
String str = "abcdef";
for(int i=0; i<1000; i++) {
      str = str + i;
}
编译器自动优化这行代码
每次循环都会生成一个新的StringBuilder实例,降低性能。
String str = "abcdef";
 
for(int i=0; i<1000; i++) {
str = (new StringBuilder(String.valueOf(str))).append(i).toString();
}
在字符串拼接时,自己要显示使用StringBuilder来提升性能。

如何使用String.intern节省内存?

String a =new String("abc").intern();
String b = new String("abc").intern();
          
if(a==b) {
    System.out.print("a==b");
}

结果
a==b

针对字符串常量,默认会将对象放入字符串常量池。
针对字符串变量,在字符串常量池中创建对象,堆中创建对象,引用字符串常量池中char数组到堆对象中,返回堆对象引用。
如果调用intern方法,查看字符串常量池中是否有同一个值的字符串。如果没有,就在字符串常量池中新增该对象,并返回该对象引用;如果有,就返回字符串常量池中的字符串引用。堆中原有的对象由于没有引用指向它,通过垃圾回收器回收。

a变量
在加载类时,在字符串常量池中创建一个“abc”字符串对象。
在调用new时,在堆中创建一个String对象。
在调用intern方法时,去字符串常量池中查找是否有等于该字符串的对象,发现有。
b变量
在加载类时,因为字符串常量池中有该字符串对象而不再创建。
在调用new时,在堆中创建一个String对象。
在调用intern方法时,去字符串常量池中查找是否有等于该字符串的对象,发现有。
而在堆中的对象,由于没有引用指向它,会被垃圾回收。所以a和b引用的是同一个对象。

intern方法本质上让变量引用字符串常量池中同一个字符串值的对象。
使用intern方法一定要结合实际场景。因为字符串常量池的实现是类似于一个HashTable的实现方式,HashTable(哈希表+单链表)存储的数据越多,遍历的时间复杂度越高。如果数据过大,会增加整个字符串常量池的负担。

参考资料

Java 性能调优实战

标签:String,对象,池中,str,字符串,常量
From: https://www.cnblogs.com/WJQ2017/p/17556207.html

相关文章

  • python Tensor 转string
    PythonTensor转string实现介绍在机器学习和深度学习中,Tensor(张量)是一个非常常见的数据结构,它是一个多维数组,用于存储和处理大规模的数据。在某些情况下,我们可能需要将一个Tensor转换为字符串,以便于输出、存储或传输。本文将向你展示如何使用Python实现这个功能。实现步骤下......
  • python中tk的simpledialog.askstring报错解决方案
    simpledialog.askstring还是比较好用的,能够很方便的获取用户输入的文本,但是在多线程中会出现下面的错误:_tkinter.TclError:window".!_querystring"wasdeletedbeforeitsvisibilitychanged解决的方案参考:https://stackoverflow.com/questions/53480400/tkinter-ask......
  • java--String类的常用方法
    一、获取1、length()  获取字符串长度Stringstr="ahcckmvevawe";System.out.println(str.length());//输出122、charAt(intindex)  返回下标对应的字符Stringstr="ahcckmvevawe";System.out.println(str.charAt(4));//输出k3、indexOf()  返回字符对......
  • gcc5 std::string的变化
    自从GCC-5.1开始,std::string引入了遵从C++11标准的新实现,默认使用SSO(smallstringoptimization)特性,禁用了写时复制(COW)引用计数机制,这也带来了与旧版本std::string的ABI兼容性问题。 参考:http://www.pandademo.com/2017/04/new-changes-of-gcc5-std-string/https......
  • springboot redis工具类之StringRedisTemplate 使用
    1、StringRedisTemplate是什么?StringRedisTemplate继承自RedisTemplate类,实现了BeanClassLoaderAware,Aware,InitializingBean,RedisOperations<K,V>接口。StringRedisTemplate是RedisTemplate以字符串为中心的扩展,由于针对Redis的大多数操作都是基于字符串的,因此此类提供了一个......
  • MyBatis返回resultType=Map的用法, 返回List<Map<String,String>>
    <selectid="statOnlineAndNotlineNumber"resultType="java.util.Map"parameterType="java.lang.String">SELECTonline_stateasstate,COUNT(online_state)asnumberFROMwl_rm_t_vehicle_state<iftest="operatorCode!=nu......
  • StringBuilder()类、chatAt()、toString()方法
    Java1.StringBuffer和StringBuilder类和String类不同的是,StringBuffer和StringBuilder类的对象能够被多次的修改,并且不产生新的未使用对象。在使用StringBuffer类时,每次都会对StringBuffer对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使......
  • JVM(十)StringTable
    JVM(十)StringTable1String的基本特性String即字符串,通过一对引号""表示,String创建的方式主要有Strings="abc";//字面量的方式Strings=newString("abc");//类创建new方式String声明为final,不可以被继承String实现了Serializable接口,表示字符串是支持序列......
  • redis数据结构-String(SDS)
    redis数据结构(一)注:以下源码部分,来自redis-7.0.12,redis-3.0redis有一个核心的对象,叫做redisObject,用来标识所有的key和value,用结构体reidsObject来标识String、Hash、List、Set、Zset五种数据结构。源码位置在server.h。/*Objectsencoding.Somekindofobjects......
  • 105.你知道const char* 与string之间的关系是什么吗?
    105.你知道constchar*与string之间的关系是什么吗?1.string是C++标准库里面其中一个,封装了对字符串的操作,实际操作过程我们可以用constchar*给string类初始化2.三者的转化关系如下所示:a)string转constchar*strings=“abc”;constchar*c_s=s.c_str();b)c......