今天到北理IT论坛的小冬分享信息了!

 以下是他所分享的信息以及大家共同探讨的内容,以此摘录 以备后用!

 2012年7月23日

 小冬:

大家都知道,String 是final的,final类意味着不可被继承,final方法是不可被重写(覆盖),而final属性是不可被修改的

我们可以从String的原码可以看到,它的属性都是private和final的

而最主要的是: private final char value[]

这就注定了String的值一经定义赋值,就不可改变,这就是String的不变性。

我们来看下它的实例化

一般有两种方式:

1、String str1 = "a";//直接赋值

2、String str2 = new String("a");//通过new关键字

其实还有一种,就是Class类

下面我们来看下一段代码:

public static void main(String args[]){

        String str1 = "hello" ;        

        String str2 = new String("hello") ;

        String str3 = "hello" ;        

        System.out.println("str1 == str2 --> " + (str1==str2)) ;//false

        System.out.println("str2 == str3 --> " + (str2==str3)) ;//false

        System.out.println("str1 == str3 --> " + (str1==str3)) ;//true

        System.out.println("str1 equals str2 --> " + str1.equals(str2)) ;// true

        System.out.println("str2 equals str3 --> " + str2.equals(str3)) ;// true

        System.out.println("str1 equals str3 --> " + (str1.equals(str3))) ;// true

}

从输出我们可以看到

明显:默认情况下,==比较的是地址,而equals 比较的是内容

接下来下面是重点,我们再来分析下它在内存空间里是怎么存放的:

在这这前说点知识

jvm的内存空间可以分为:堆空间,栈空间和方法区

栈空间存放的是我们定义的变量

堆 中放的是对应的信息

而方法区中存放的是Class类信息

如:String str1 = "hello" ;

栈空间存放就是变量str1

堆中放的就是:"hello"

方法区中的,可以关系到反射,以后再可以和大家探讨

我们再回到String

如图:

第一次str1 = "hello"时创建一个空间,

第二次因为用是new关键字会再创建一个空间,只是空间里放的东西是一样的

第三次 str3 = "hello"时却不会创建新的空间而是指向了第一次创建的空间

我们会想,显然直接赋值也是会创建空间的,那为什么第三次也是直接赋值却不会创建空间呢?

 

还有它为什么是指向第一次创建的空间而不是第二次的呢?

它是根据什么确定指向空间的?

是内存中的顺序排第一个的?

 

 

为了验证下,我们把代码的位置调整下,把String str2 = new String("hello") 放在String str1 = "hello"的前面

再把JVM关了重新打开,运行代码,结果是str3指向的依然是str1创建的空间。

这是为什么呢?大家可以讨论下,到底直接赋值的方式它是怎么实现的?

 

 

用了new都会新创建空间

 

10**敏  10:26:20

用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享

 

 

10小冬  10:32:23

嗯 ,差不多,我的理解是朝翔说到的池的概念,通过直接赋值的方式创建的对象会放在一个池里,而new方式创建的对象并不会放到那个池中,下次再通过直接赋值的方式创建的对象时会先从池中找有没有值一样的对象,有的话就返回给它,没有再新建

 

10**敏  11:17:11

栈,堆,字符串池是分开的吧,用new的话,应该是三个地方都会有?

 

**翔(广州) 11:28:34

to 颖敏:如果是匿名对象,不需要用到栈,否则,三者都会用到,池不是堆,是另外一个专门为字符串等设置的机制,类似以操作系统的cache,高速缓冲存储器,即缓存,目的就是提高效率。 

10小冬(珠海)  11:29:47

str1+str2+str3是会新建空间的,先一个空间存放str1和str2连接起来的内容,再创建一个空存放第一个空间的值和str3连接的值,所以如果多字符串连接一般不用+

 

 

10**翔(广州) 11:33:14

是,准确来说是在堆中复制一份,然后放入池中,这里用到了clone,其实克隆也是产生对象的一种方式,被很多人遗漏。

而谁来管理池呢?这里又会带出线程的概念,没完没了。。。

这也就验证了一个事实:知道的越多,就会越痛苦。 

10小冬(珠海) 11:38:28

clone也分为深clone和浅clone

10**翔(广州) 11:38:47

所以就不如回到原点:没事别乱new,new一般是用在字符转换的场合。