写点什么

String 的内存分配与拼接操作,mysql 数据库教程课后题答案

用户头像
极客good
关注
发布于: 刚刚


  • 在 jdk6 中 StringTable 是固定的,就是 1009 的长度,所以如果常量池中的字符串过多就会导致效率下降很快,StringTablesize 设置没有要求。


  • 在 jdk7 中,StringTable 的长度默认值是 60013,StringTablesize 设置没有要求


  • 在 jdk8 中,设置 StringTa


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


ble 长度的话,1009 是可以设置的最小值


[](


)String 的内存分配




在 Java 语言中有 8 种基本数据类型和一种比较特殊的类型 String。这些类型为了使它们在运行过程中速度更快、更节省内存,都提供了一种常量池的概念。


常量池就类似一个 Java 系统级别提供的缓存。8 种基本数据类型的常量池都是系统协调的,String 类型的常量池比较特殊,存储的主要方法有两种:


  • 直接使用双引号声明出来的 String 对象会直接存储在常量池中。

  • 如果不是用双引号声明的 String 对象,可以使用 String 提供的 intern()方法。


在 JDK 7 以后,内部字符串不再分配在 Java 堆的永久代中(永久代垃圾回收频率低)而是分配在 Java 堆的主要部分(年轻代和老年代),所有的字符串都保存在堆中,与应用程序创建的其他对象放在一起。这种变化将导致更多的数据驻留在主 Java 堆中,而更少的数据在永久代中,因此可能需要调整堆的大小。



在加载许多类或大量使用 String.intern()方法的大型应用程序中可以看到这个改动的明显效果。


样例:


class Memory {


public static void main(String[] args) {//line 1


int i= 1;//line 2


Object obj = new Object();//line 3


Memory mem = new Memory();//Line 4


mem.foo(obj);//Line 5


}//Line 9


private void foo(Object param) {//line 6


String str = param.toString();//line 7


System.out.println(str);


}//Line 8


}



[](


)字符串拼接操作




  • 常量与常量的拼接结果在常量池,原理是编译期优化

  • 常量池中不会存在相同内容的变量

  • 只要其中有一个是变量,结果就在堆中。变量拼接的原理是 StringBuilder

  • 如果拼接的结果调用 intern()方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象地址


举例 1:


public static void test1() {


// 都是常量,前端编译期会进行代码优化


String s1 = "a" + "b" + "c";


String s2 = "abc";


// true,有上述可知,s1 和 s2 实际上指向字符串常量池中的同一个值


System.out.println(s1 == s2);


}


反编译为 class 文件后,会发现 String s1 = “abc”; 说明代码在编译期进行了优化



举例 2:


public static void test2() {


String s1 = "javaEE";


String s2 = "hadoop";


String s3 = "javaEEhadoop";


String s4 = "javaEE" + "hadoop";


String s5 = s1 + "hadoop";


String s6 = "javaEE" + s2;


String s7 = s1 + s2;


System.out.println(s3 == s4); // true 编译期优化


System.out.println(s3 == s5); // false s1 是变量,不能编译期优化


System.out.println(s3 == s6); // false s2 是变量,不能编译期优化


System.out.println(s3 == s7); // false s1、s2 都是变量


System.out.println(s5 == s6); // false s5、s6 不同的对象实例


System.out.println(s5 == s7); // false s5、s7 不同的对象实例


System.out.println(s6 == s7); // false s6、s7 不同的对象实例


String s8 = s6.intern();


System.out.println(s3 == s8); // true intern 之后,s8 和 s3 一样,指向字符串常量池中的"javaEEhadoop"


}


变量拼接原理:


当两个变量:String s1=“a”;String s2=“b”;相加时:其执行细节如下:


①StringBuilder s=new StringBuilder();


②s.append(“a”);


③s.append(“b”);


④s.toString();


举例 3:


public void test3(){


String s0 = "ab";


String s1 = "a";


String s2 = "b";


String s3 = s1 + s2;


System.out.println(s0 == s3); // false s3 指向对象实例,s0 指向字符串常量池中的"ab"


String s7 = "cd";


final String s4 = "c";


final String s5 = "d";


String s6 = s4 + s5;


System.out.println(s6 == s7); // true s4 和 s5 是 final 修饰的,编译期就能确定 s6 的值了


}


字符串拼接操作不一定使用的时 StringBuilder,如果使用 final 修饰,即为常量,会在编译器进行代码优化。如果不使用 final 修饰,即为变量,会通过 new StringBuilder 进行拼接。在实际开发中,能够使用 final 的,尽量使用。


举例 4:


字符串拼接操作性能对比:


public class Test{


public static void main(String[] args) {


int times = 40000;


long start = System.currentTimeMillis();


testString(times); // String 6963ms


//testStringBuilder(times); // StringBuilder 2ms


long end = System.currentTimeMillis();


System.out.println("String: " + (end-start) + "ms");


}


public static void testString(int times) {


String str = "";

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
String的内存分配与拼接操作,mysql数据库教程课后题答案