当时看时以为是一个,最后发现是两个对象,一个引用变量s ,其中两个对象分别是new String()在堆中,另一个是"xyz"创建在常量池,在网上也查过,这个"xyz"存在常量池中是否算成对象有很多争议。
其中有三个基本知识点要熟悉下,分别是堆和栈、常量池。
栈 :由JVM分配区域,用于保存线程执行的动作和数据引用。 堆 :由JVM分配的,用于存储对象等数据的区域。 常量池(constant pool) :在堆中分配出来的一块存储区域,用于存储显式 的 String,float或者integer.这是一个特殊的共享区域,可以在内存中共享的不经常改变的东西,都可以放在这里。
String c = new String("xyz");① String d = new String("xyz");② ①Class被CLassLoader加载时,你的"xyz"被作为常量读入,在constant pool里创建了一个共享的"xyz",然后当调用到new String("xyz")的时候,会在heap里创建这个new String("xyz"); ②由于constant pool中存在"xyz"所以不再创建"xyz",然后创建新的new String("xyz")。
对于String c = new String("xyz");的代码,与String a = "abc"不同的是一概在堆中创建新对象,不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。 String s1 = new String("xyz"); //创建二个对象,一个引用 所以两个对象:一个在heap中,一个在String常量池。
String s2 = new String("xyz"); //创建一个对象,并且以后每执行一次创建一个对象,一个引用 String s3 = "xyz"; //创建一个对象,一个引用
String s4 = "xyz"; //不创建对象,只是创建一个新的引用 这个跟常量池没有关系,只要是new,都是重新分配堆空间,如果不区分栈和堆,这里创建了1个String Object。如果是从jvm角度来说的话, 它是创建了两个对象,String s是在栈里创建了一个变量,new String("xyz")是在堆里创建了一个对象并被s引用到。 所以说是有两个对象,一个引用变量
|