String s="abc"这个"abc"是在那里开辟的空间,栈里还是堆里???

解决方案 »

  1.   

     我们知道得到String对象有两种办法: String str1="hello"; String str2=new String("hello"); 这两种创建String对象的方法有什么差异吗?当然有差异,差异就在于第一种方法在对象池中拿对象,第二种方法直接生成新的对象。"abc"属于字符串池中,是放在栈中。String str = "abc"; 在内存中"abc"存放在栈
    String str1 = new String("abc"); 在内存中new String("abc")被存放在堆程序运行时,我们最好对数据保存到什么地方做到心中有数。特别要注意的是内存的分配。有六个地方都可以保存数据:
    (1) 寄存器。这是最快的保存区域,因为它位于和其他所有保存方式不同的地方:处理器内部。然而,寄存器的数量十分有限,所以寄存器是根据需要由编译器分配。我们对此没有直接的控制权,也不可能在自己的程序里找到寄存器存在的任何踪迹。
    (2) 堆栈。驻留于常规RAM(随机访问存储器)区域,但可通过它的“堆栈指针”获得处理的直接支持。堆栈指针若向下移,会创建新的内存;若向上移,则会释放那些内存。这是一种特别快、特别有效的数据保存方式,仅次于寄存器。创建程序时,Java编译器必须准确地知道堆栈内保存的所有数据的“长度”以及“存在时间”。这是由于它必须生成相应的代码,以便向上和向下移动指针。这一限制无疑影响了程序的灵活性,所以尽管有些Java数据要保存在堆栈里——特别是对象句柄,但Java对象并不放到其中。
    (3) 堆。一种常规用途的内存池(也在RAM区域),其中保存了Java对象。和堆栈不同,“内存堆”或“堆”(Heap)最吸引人的地方在于编译器不必知道要从堆里分配多少存储空间,也不必知道存储的数据要在堆里停留多长的时间。因此,用堆保存数据时会得到更大的灵活性。要求创建一个对象时,只需用new命令编制相关的代码即可。执行这些代码时,会在堆里自动进行数据的保存。当然,为达到这种灵活性,必然会付出一定的代价:在堆里分配存储空间时会花掉更长的时间!
    (4) 静态存储。这儿的“静态”(Static)是指“位于固定位置”(尽管也在RAM里)。程序运行期间,静态存储的数据将随时等候调用。可用static关键字指出一个对象的特定元素是静态的。但Java对象本身永远都不会置入静态存储空间。
    (5) 常数存储。常数值通常直接置于程序代码内部。这样做是安全的,因为它们永远都不会改变。有的常数需要严格地保护,所以可考虑将它们置入只读存储器(ROM)。
    (6) 非RAM存储。若数据完全独立于一个程序之外,则程序不运行时仍可存在,并在程序的控制范围之外。其中两个最主要的例子便是“流式对象”和“固定对象”。对于流式对象,对象会变成字节流,通常会发给另一台机器。而对于固定对象,对象保存在磁盘中。即使程序中止运行,它们仍可保持自己的状态不变。对于这些类型的数据存储,一个特别有用的技巧就是它们能存在于其他媒体中。一旦需要,甚至能将它们恢复成普通的、基于RAM的对象。Java 1.1提供了对Lightweight persistence的支持。未来的版本甚至可能提供更完整的方案。 
      

  2.   


    String是一个特殊的包装类数据。可以用:String str = new String(“abc”);String str = “abc”;两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。而第二种是先在栈中创建一个对String类的对象引用变量str,然后查找栈中有没有存放”abc”,如果没有,则将”abc”存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。String str1 = “abc”;String str2 = “abc”;System.out.println(str1==str2); //true可以看出str1和str2是指向同一个对象的。String str1 =new String (“abc”);String str2 =new String (“abc”);System.out.println(str1==str2); // false用new的方式是生成不同的对象。每一次生成一个。因 此用第二种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String(“abc”);的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。另 一方面, 要注意: 我们在使用诸如String str = “abc”;的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的 对象。只有通过new()方法才能保证每次都创建一个新的对象。
      

  3.   

    "abc"放在数据段中
    s 放在栈中,指向"abc"
      

  4.   

    "abc"放在数据段中
    s 放在栈中,指向"abc"
      

  5.   

    String s="abc"
    你一看就知道s是个引用,那引用当然存在栈里,那引用指向的就是对象了,所以"abc"是对象,那对象自然就是存放在堆里了
      

  6.   

    对象引用和普通数据类型在栈里,java对象放在堆里
      

  7.   

    麻烦各位不懂的就不要误导人了好不好,对自己的言论要负责任的,就11楼的说的正确!!!
    其它的话虽然正确但没针对LZ的问题。
    一个由c/c++编译的程序(很遗憾我们的JVM虚拟机基本上使用c/c++写的)占用的内容分以下五个部分:
    1、栈区:存放函数的参数值,局部变量的值等,由编译器自动分配释放。对象的引用其实就是一个地址值当然是存放在这里的。
    2、堆区:引用所指向的对象就分配在堆里。
    例如:A a = new A(); a 在栈里,new A() 就在堆里。这里的a其实就是一个地址值。
    3、全局区(静态区):全部变量和静态变量是放在一块的,而且初始化的和未初始化是分开存放的。
    4、文字常量区:常量字符串就是放在这里的。
    回到楼主的问题:String s="abc"; s在栈里, "abc"就在这个区里面!!!
    5、程序代码区:存放函数体的二进制代码 
      

  8.   

    String s="abc";
    String a="abc";实际上s 与 a指向的是一片内存
      

  9.   

    昵称改成   凤儿's_Jhon'
    不然又得误会了,呵呵