当前位置: 首页 > article >正文

Java String相关问题

一、String 的不可变特性

String 可能是 Java 中最特殊的一个数据类型。

  • 和基本数据类型的封装类型一样,具备不可变性
  • 声明方式像基本数据类型,但其实是引用类型
  • 作为引用类型,又不一定直接放在里,有可能放在字符串池(String Pool)中;

String 的不可变特性体现在哪些方面呢?

首先,String 类是一个 final,它不能被继承

public final class String implements Serializable, Comparable<String>, CharSequence {
   ** 用来存储字符 *private final char[] value; 
	......
}

其次,它的内部真正用来存储字符的 value 数组也是一个 final 类型的,不能被修改指向

此外,String类中所有外部能调用的操作,凡是返回String对象的操作方法都是返回一个新的String实例对象

public String subString( int begin ) {
   
	......
	return (beginIndex == 0) ? this : new String(value, begin, subLen); 
}

也就是说,不管你怎么操作,最开始的String对象一定是不变的,你得到的所有String新实例都是新生成的(当然新生成的也是不可变的),而不会去修改原本的对象。

在这里插入图片描述

所以,总结一下String 的不可变特性主要体现在两个方面:

  • 不可变的类(包括数据成员)
  • 不可变的实例对象

二、String 为什么要设计成不可变的?

  1. 使用习惯需要:
String fileName = "demo.jar"; 
String dirPath = “disk/code/";
String filePath = dirPath + fileName;

String 实例的使用,主要是对字面量的使用,更接近基本数据类型。

  1. 计算需要:加快字符串处理速度
public final class String implements Serializable, Comparable<String>, CharSequence {
   ** 缓存字符串的hash code *private int hash;
	......
	public int hashCode() {
   
		int h = hash;
		if (h == 0 && value.length > 0) {
    
			char val[] = value;
			for (int i = 0; i < value.length; i++)	{
   
				h =(31 * h + val[i]; // 将每一位的特征在末位不断累加
			}
			hash = h; 
		}
		return h; 
	}
}

我们发现 Stringhash 值是计算出来以后缓存在内部的,假如 Stringvalue 数组可变,那么可能每次改变 value 数组都要重新计算 hash 值,效率降低。

由于String是不可变的,保证了hashcode的唯一性,于是在创建对象时其hashcode就可以放心的缓存了,不需要重新计算。这也就是Map喜欢将String作为Key的原因,处理速度要快过其它的键对象。所以HashMap中的键往往都使用String

  1. 线程安全需要:

例如以下代码:

public StringBuilder addSuffix(StringBuilder builder) {
    
	return builder.append(.jar");
}

// 这里的 StringBuilder 不具备线程可见性,且 StringBuilder 是可变类 
String fileNameBuilder = new StringBuilder("demo"); 
String fullFileName = "";

fullFileName = addSuffix(fileNameBuilder).toString(); // 并发执行 
fullFileName = addSuffix(fileNameBuilder).toString(); // 并发执行

在不加锁的前提下,假设有两个线程同时调用 addSuffix 方法并将结果赋值给 fullFileName ,那么 fullFileName 结果是 demo.jar 还是 demo.jar.jar?显然这无法得到线程安全的保证。

如果换成是 String,就能保证绝对线程安全,结果一定是 demo.jar

public String addSuffix(String str) {
    
	

http://www.kler.cn/news/161893.html

相关文章:

  • StringBoot常用注解(不断添加)
  • ncnn模型部署——使用VS2019把项目打包成DLL文件
  • 【头歌实训】分布式文件系统 HDFS
  • 火狐,要完了!
  • GateWay网关介绍以及整合knife4j聚合所有服务的接口文档
  • pymol使用
  • EI级 | Matlab实现TCN-GRU-Multihead-Attention多头注意力机制多变量时间序列预测
  • TE发布最新TC Policy 3.1
  • 单片机第三季-第四课:STM32下载、MDK和调试器
  • 网站建设app开发小程序制作|企业软件定制
  • 有爱的冬天不再冷——壹基金儿童温暖包抵达富平
  • Kubernetes(K8s)Pod控制器详解-06
  • Java的List中的各种浅拷贝和深拷贝问题
  • 超大规模集成电路设计----FPGA时序模型及FSM的设计(八)
  • 查看端口号是否被占用
  • 指针数组和数组指针作为形式参数
  • SmartChart:一站式数据可视化解决方案
  • SpringBoot:SpringMVC(上)
  • 2023-12-04 AIGC-Stable Diffusion和SadTalker-搭建及使用
  • Linux_CentOS_7.9 VNC安装卸载以及相关配置开机自启动服务简易记录
  • 字符串排序
  • 【华为数据之道学习笔记】3-2 基础数据治理
  • JavaEE之多线程编程(一):基础篇
  • 手机升级到iOS15.8后无法在xcode(14.2)上真机调试
  • ubuntu 14.04的git 错误: gnutls_handshake() failed: Handshake failed
  • 华为云安全组规则
  • Android 11.0 MTK Camera2 设置默认拍照尺寸功能实现
  • vue3日常知识点学习归纳
  • 第 7 部分 — 增强 LLM 安全性的策略:数学和伦理框架
  • 微前端 -- wujie 预加载和原理 无界传参