java核心基础 --- String.intern

本文详细解析了Java字符串常量池的工作原理,对比了JDK6与JDK7中字符串常量池的位置变化及intern方法的行为差异,并通过代码示例展示了不同版本下对象引用的处理方式。

本篇博文转载自:
https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html

相信很多 JAVA 程序员都做过类似 String s = new String("abc") 这语句创建了几个对象的题目。这种题目主要就是为了考察程序员对字符串对象的常量池掌握与否。上述的语句中是创建了 2 个对象,第一个对象是 “abc” 字符串存储在常量池中,第二个对象在 JAVA Heap 中的 String 对象。

除此之外,我们还应该掌握 String 常量池的相关知识。它的主要使用方法有两种:

  • 直接使用双引号声明出来的 String 对象会直接存储在常量池中
  • 如果不是使用双引号声明的 String 对象,可以使用 String 提供的 intern 方法。intern 方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中。不过这个方法在 JDK6 和 JDK7 中却会表现出不一样的行为,接下来我们来看看他们的区别。

先来看一段代码:

public static void main(String[] args){
    String s = new String("1");
    s.intern();
    String s2 = "1";
    System.out.println(s == s2);
    
    String s3 = new String("1") + new String("1");
    s3.intern();
    String s4 = "11";
    System.out.println(s3 == s4);
}

打印结果为:

  • jdk6 下 false false
  • jdk7 下 false true

具体为什么稍后解释,然后将 s3.intern(); 语句下调一行,放在 String s4 = "11" 后面。将 s.intern() 放在 String s2 = "1" 后面。是什么结果呢?

public static void main(String[] args) {
    String s = new String("1");
    String s2 = "1";
    s.intern();
    System.out.println(s == s2);

    String s3 = new String("1") + new String("1");
    String s4 = "11";
    s3.intern();
    System.out.println(s3 == s4);
}

打印结果为:

  • jdk6 下 false false
  • jdk7 下 false false

JDK6 中的解释

jdk6图

注:图中绿色线条代表 string 对象的内容指向。黑色线条代表地址指向

如上图所示。首先说一下 jdk6 中的情况,在 jdk6 中上述的所有打印都是 false 的,因为 jdk6 中的常量池是放在 perm(是一个类静态的区域,主要存储一些加载类信息,常量池,方法片段等内容) 区中的,Perm 区和正常的 JAVA Heap 区域是完全分开的。上面说过如果是使用引号声明的字符串都是会直接在字符串常量池中生成,而 new 出来的 String 对象是放在 JAVA Heap(堆) 区域。所以拿一个 JAVA Heap 区域的对象地址和字符串常量池的对象地址进行比较肯定是不相同的,即使调用 String.intern 方法也是没有任何关系的。

JDK7 中的解释

再说说 JDK7 中的情况,这里要明确的一点是,在 JDK7 的版本中,字符串常量池已经从 Perm 区域移到正常的 Java Heap 区域了,现在来解释为什么会有上述的打印结果。

jdk7图1

  • 在第一段代码中,先看 s3 和 s4 字符串。String s3 = new String("1") + new String("1"),这句代码中现在生成了 2 个对象,是字符串常量池中的 1 和 JAVA Heap 中的 s3 引用指向的对象。中间还有 2 个匿名的 new String(“1”) 我们不去讨论他们。此时 s3 引用对象内容是 “11”,但此时常量池中是没有 “11” 对象的。
  • 接下来 s3.intern 这一句代码,是将 s3 中的 11 字符串放入 String 常量池中,因为此时常量池中不存在 11 字符串,因此常规的做法是跟 jdk6 图中表示的那样,在常量池中生成一个 11 对象,关键点是 jdk7 中常量池不在 Perm 区域了,这块做了调整。常量池中不需要再存储一份对象了,可以直接存储堆中的引用。这份引用指向 s3 引用的对象。也就是说引用地址是相同的。
  • 最后 String s4 = “11” 这句代码中 11 是显示声明的,因此会直接去常量池中创建,创建的时候发现已经有这个对象了,此时也就是指向 s3 引用对象的一个引用。所以 s4 引用就指向和 s3 一样了。因此最后的比较 s3 == s4 是 true。
  • 再看 s 和 s2 对象。String s = new String(“1”) 这一句代码,生成了 2 个对象。常量池中的 1 和 JAVA Heap 中的字符串对象。s.intern() 这一句是 s 对象去常量池中寻找后发现 1 已经存在常量池了
  • 接下来 String s2 = “1” 这句代码是生成一个 s2 的引用指向常量池中的 1 对象。结果就是 s 和 s2 的引用地址明显不同。图中画的很清晰。

jdk7图2

  • 来看第二段代码,从上边第二幅图中观察。第一段代码和第二段代码的改变就是 s3.intern 的顺序放在 String s4 = "11"后了。这样,首先执行 String s4 = “11” 声明 s4 的时候常量池中是不存在 11 对象的,执行完毕后,11 对象是 s4 声明产生的对象。然后再执行 s3.intern 时,常量池中 11 对象已经存在,此时 s3 和 s4 的引用是不同的。
  • 第二段代码中的 s 和 s2 代码中,s.intern 这一句往后放也不会有什么影响了,因为对象池中在执行第一句代码 String s = new String(“1”) 的时候已经生成了 1 对象了。下边的 s2 声明都是直接从常量池中取地址引用的。s 和 s2 的引用地址是不会相同的。

小结

从上述的例子代码可以看出 jdk7 版本对 intern 操作和敞亮池都做了一定的修改。主要包括 2 点:

  • 将 String 常量池从 Perm 区域移动到了 JAVA Heap 区域
  • 使用 String.intern 方法时,如果存在堆中的对象,会直接保存对象的引用,而不会重新创建对象。
内容概要:本文详细介绍了一种基于Simulink的表贴式永磁同步电机(SPMSM)有限控制集模型预测电流控制(FCS-MPCC)仿真系统。通过构建PMSM数学模型、坐标变换、MPC控制器、SVPWM调制等模块,实现了对电机定子电流的高精度跟踪控制,具备快速动态响应和低稳态误差的特点。文中提供了完整的仿真建模步骤、关键参数设置、核心MATLAB函数代码及仿真结果分析,涵盖转速、电流、转矩和三相电流波形,验证了MPC控制策略在动态性能、稳态精度和抗负载扰动方面的优越性,并提出了参数自整定、加权代价函数、模型预测转矩控制和弱磁扩速等优化方向。; 适合人群:自动化、电气工程及其相关专业本科生、研究生,以及从事电机控制算法研究与仿真的工程技术人员;具备一定的电机原理、自动控制理论和Simulink仿真基础者更佳; 使用场景及目标:①用于永磁同步电机模型预测控制的教学演示、课程设计或毕业设计项目;②作为电机先进控制算法(如MPC、MPTC)的仿真验证平台;③支撑科研中对控制性能优化(如动态响应、抗干扰能力)的研究需求; 阅读建议:建议读者结合Simulink环境动手搭建模型,深入理解各模块间的信号流向与控制逻辑,重点掌握预测模型构建、代价函数设计与开关状态选择机制,并可通过修改电机参数或控制策略进行拓展实验,以增强实践与创新能力。
根据原作 https://pan.quark.cn/s/23d6270309e5 的源码改编 湖北省黄石市2021年中考数学试卷所包含的知识点广泛涉及了中学数学的基础领域,涵盖了实数、科学记数法、分式方程、几何体的三视图、立体几何、概率统计以及代数方程等多个方面。 接下来将对每道试题所关联的知识点进行深入剖析:1. 实数与倒数的定义:该题目旨在检验学生对倒数概念的掌握程度,即一个数a的倒数表达为1/a,因此-7的倒数可表示为-1/7。 2. 科学记数法的运用:科学记数法是一种表示极大或极小数字的方法,其形式为a×10^n,其中1≤|a|<10,n为整数。 此题要求学生运用科学记数法表示一个天文单位的距离,将1.4960亿千米转换为1.4960×10^8千米。 3. 分式方程的求解方法:考察学生解决包含分母的方程的能力,题目要求找出满足方程3/(2x-1)=1的x值,需通过消除分母的方式转化为整式方程进行解答。 4. 三视图的辨认:该题目测试学生对于几何体三视图(主视图、左视图、俯视图)的认识,需要识别出具有两个相同视图而另一个不同的几何体。 5. 立体几何与表面积的计算:题目要求学生计算由直角三角形旋转形成的圆锥的表面积,要求学生对圆锥的底面积和侧面积公式有所了解并加以运用。 6. 统计学的基础概念:题目涉及众数、平均数、极差和中位数的定义,要求学生根据提供的数据信息选择恰当的统计量。 7. 方程的整数解求解:考察学生在实际问题中进行数学建模的能力,通过建立方程来计算在特定条件下帐篷的搭建方案数量。 8. 三角学的实际应用:题目通过在直角三角形中运用三角函数来求解特定线段的长度。 利用正弦定理求解AD的长度是解答该问题的关键。 9. 几何变换的应用:题目要求学生运用三角板的旋转来求解特定点的...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值