我们知道,JAVA中,内置类型都是在栈上分配内存的;而自定义类型是在堆上分配。
每个自定义类型的变量名都是一个引用,绑定到一个在堆上分配的自定义对象。
我的猜想是,这个引用就是一个指向堆上某位置的地址,这个变量名保存这个地址以达到绑定。
我的疑问是:这个引用(也就是这个地址)的信息是存在哪里的?堆上还是栈上?以何种方式?
谢谢。

解决方案 »

  1.   

    看到这句:我们知道,JAVA中,内置类型都是在栈上分配内存的就已经知道是错误的了。其它就不看了。
      

  2.   

    本人初学JAVA
    那段话是在THINKING IN JAVA中看到的啊。
    原文如下:
    此类变量(基本类型)直接存放数据值,并置于stack...
    不知哪里错了。
      

  3.   

    public class Person{
        private int age=100;
    }
    请问:age是不是内置基本类型?但是是在栈上上分配的吗?
      

  4.   

    楼主你说的没有错,Java 8大基本数据类型(实际上是9种类型)是在 栈分配内存的,其他封装类型在堆分配,Java在堆分配内存比C++要快很多,因为C++在分配的时候需要计算出拿块是空的,而Java堆分配内存时是采用类似传送带的方式,会把已分配内存聚集,所以创建对象的速度远大于C++,另外回答你的问题:我也看过几遍Think in java , 记得引用地址应该是存放在栈内存。
      

  5.   

    LZ应该是基本理解的,但表述上不精确。
    我的理解,
    基本类型 和 对象引用(包括数组引用) 同属于最基本的数据,
    分配在当前所用的内存中。比如在方法内声明的局部变量(基本类型)、引用,都在栈上分配。
    若是作为类中的非成员变量,
    则放在 new 具体实例时,从堆中取的那块内存中。
    静态成员等类推。
      

  6.   

    这是我的一点理解,拿出来和楼主讨论
    Java堆与栈
    Java的堆是一个位于随机访问存储器(RAM)的运行时数据区。通常使用new操作符在堆中创建对象,它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。 Java的栈也位于RAM,它的存取速度比堆要快,仅次于寄存器且据可以共享,主要存放一些基本类型的变量和对象的引用;但存在于栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义: int a = 3; 
     
    int b = 3; 
     
    编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着处理int b = 3;在创建完b的引用变量后,由于在栈中查找到3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。 这时,如果再令a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。好了,我们再来看上面的例子:Integer i1 = 12;
     
    Integer i2 = 12;
     
    System.out.println(i1==i2);         //true
     
    由于是自动包装,对于从–128到127之间的值,它们被包装为Integer对象后,会存在内存中被重用,因此输出的是true;i1=new Integer(13);
     
    i2=new Integer(13);
     
    System.out.println(i1==i2);         //flase
     
    由于使用的是new操作符,而不是自动包装功能,Java在堆里面创建了两个Integer对象,分别与i1和i2关联,由于==对于对象比较的是引用,所以输出是false;然而下面的语句中实际上只创建了一个对象,这里又出现的别名的现象i1=i2=new Integer(14);
     
    System.out.println(i1==i2);
     
    因此用第一种方式创建多个int,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于Integer i = new Integer (int);的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。好了,这样以来相信下面的程序也不会为我们带来太多的疑惑了:view plaincopy to clipboardprint?
      public static void main(String args[])   
      {   
          Integer i1=new Integer(13);   
          Integer i2=new Integer(13);   
          int i3=13;   
          System.out.println(i1==i2);   
          System.out.println(i2==i3);   
          System.out.println(i3==i1);   
      }   
    * Output   
    * false  
    * true  
    * true  
    */  本文来自CSDN博客,转载请标明出处:http://writeblog.csdn.net/PostList.aspx
      

  7.   

    http://blog.csdn.net/KingWolfOfSky/archive/2009/08/13/4444231.aspx
      

  8.   

    简单一点的说
    int a=3,a在栈中,3在堆中
    但是,楼主你的描述:
    这个引用(也就是这个地址)
    引用并不是地址只是堆中3的地址返回给这个引用a
    也就是说,这个地址就是在堆中,只是栈得到了它,或者说指向了它,而它的值是3
      

  9.   

    http://blog.csdn.net/silentbalanceyh/archive/2009/10/13/4661230.aspx,提供给你,希望对你有帮助,前段时间整理的
      

  10.   

    java程序内存主要分为了2个部分,包括 stack segment(栈内存区)、heap segment(堆内存区)。
    首先看看
    String s1 = new String("abc"); 
    其实这条语句是下面两条语句的缩写,
    String s1; //1
    s1=new String(“abc”); //2
    1. 在栈内存中定义一个名为s1的对String类的对像引用变量
    2. 在堆内存开辟了一块空间用于存放字符串“abc”,将1定义的引用变量s1指向该空间。