public static void main(String[] args) {
    // TODO Auto-generated method stub
    Collection c = new ArrayList();
    c.add("String");
    test(c);
    System.out.println(c.size());
    System.out.println(c.toString());
}
private static void test(Collection c) {
    // TODO Auto-generated method stub
    int i=100;
    c.add(i);
}i是test()的局部变量,但是i进入到了ArrayList了, 当离开test()作用域后,为什么i的值还存在?
内部做了那些内容?
本人小白,刚开始学习JAVA,希望大神们前来解释^^Java

解决方案 »

  1.   

    参数传递传的是Collection 的引用
      

  2.   

    嗯,是的。但是i脱离了这个函数test()后,为什么在c中还有值啊?
      

  3.   

    因为i的值被复制进了ArrayList。
      

  4.   

    这个解释不专业。
    我自己给一个解释:
    1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。
    2. 当test()调用完毕后,i 这个变量自动销毁。
    你看这个解释如何?
    但是,不知道如何验证?
      

  5.   

    这个解释不专业。
    我自己给一个解释:
    1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。
    2. 当test()调用完毕后,i 这个变量自动销毁。
    你看这个解释如何?
    但是,不知道如何验证?
    即便是装箱,i也是被复制过一次。至于是否销毁,这个无法验证,因为编译器阻止你在变量的作用范围之外引用它。你只能反问,为什么编译器要这么做?答案只能是,那个变量已经不存在了
      

  6.   

    好吧如果i在byte的取值范围之内它就不是复制,不过这个也属于细节。假设i的值是1000好了
      

  7.   

    int i=100;
    c.add(i);
    个人认为,这儿add的是i的引用(如果是一个对象,更容易理解一些),结束test方法后,虽然作用域不在了,但是内存里面i的引用还是在的,而因为collection还在使用这个引用,也不会对其进行回收。
      

  8.   

    这里的i是local primitive variable,不存在别人对其的引用
      

  9.   

    c.add() 方法肯定会发生装箱操作,因为方法的参数是object类型的,值类型不能直接转换为object类型,所以自动装箱为对应的包装类类型
    至于变量i 因为局部变量都是在栈上的,当作用域也就是大括号被执行完之后,就会在内存中消失掉另外,第一次画图,效果不是很好,不好意思!!!
      

  10.   

    这里的i是local primitive variable,不存在别人对其的引用
    任意变量均会占用内存空间,为什么没有引用?难道凭空出来?
    作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。
      

  11.   

    这个解释不专业。
    我自己给一个解释:
    1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。
    2. 当test()调用完毕后,i 这个变量自动销毁。
    你看这个解释如何?
    但是,不知道如何验证?
    即便是装箱,i也是被复制过一次。至于是否销毁,这个无法验证,因为编译器阻止你在变量的作用范围之外引用它。你只能反问,为什么编译器要这么做?答案只能是,那个变量已经不存在了
    这个不是叫做复制吧。这个应该是自动装箱的过程,在堆里面的新内存。
      

  12.   

    这里的i是local primitive variable,不存在别人对其的引用
    任意变量均会占用内存空间,为什么没有引用?难道凭空出来?
    作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。
    int a;
    if (....) {
      int i = 10;
      a = i;
    }
    假设变量a的内存地址是1000,i的内存地址是996
    出了if{...}之后,i就被销毁,a与i没有任何关系,除了它们的内存里的值相同,并不是a引用了i
      

  13.   


    你的意思是 i 是 byte 类型吗?
      

  14.   

    这个解释不专业。
    我自己给一个解释:
    1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。
    2. 当test()调用完毕后,i 这个变量自动销毁。
    你看这个解释如何?
    但是,不知道如何验证?
    即便是装箱,i也是被复制过一次。至于是否销毁,这个无法验证,因为编译器阻止你在变量的作用范围之外引用它。你只能反问,为什么编译器要这么做?答案只能是,那个变量已经不存在了
    这个不是叫做复制吧。这个应该是自动装箱的过程,在堆里面的新内存。

    打开Integer类,看valueOf(int)方法。所谓装箱,就是自动调用这个方法。所谓copy by value,就是复制了这个变量的值。
    Integer的确是在堆里面,那是因为它是一个对象,而它所封装的int是它的一个成员,也在堆里面。但是这个成员变量的值是哪里来的,是不是从i这个源头复制过来的呢?
      

  15.   


    你的意思是 i 是 byte 类型吗?
    自动装箱过程,去看Integer.valueOf(int)的源代码。如果i在byte的取值范围之内,装箱的结果是预先建立好的Integer对象,对象中封装的成员变量的值并不是直接从i处得来
      

  16.   

    这里的i是local primitive variable,不存在别人对其的引用
    任意变量均会占用内存空间,为什么没有引用?难道凭空出来?
    作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。
    int a;
    if (....) {
      int i = 10;
      a = i;
    }
    假设变量a的内存地址是1000,i的内存地址是996
    出了if{...}之后,i就被销毁,a与i没有任何关系,除了它们的内存里的值相同,并不是a引用了i
    i是变量,不是内存,销毁的仅仅是i这个变量,而值还是在内存里面,如果这个地址没有被任何对象引用,那么才会在一定时间内被JVM回收。引用指的是引用地址,而不是谁引用谁,OK?
      

  17.   

    这个解释不专业。
    我自己给一个解释:
    1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。
    2. 当test()调用完毕后,i 这个变量自动销毁。
    你看这个解释如何?
    但是,不知道如何验证?
    即便是装箱,i也是被复制过一次。至于是否销毁,这个无法验证,因为编译器阻止你在变量的作用范围之外引用它。你只能反问,为什么编译器要这么做?答案只能是,那个变量已经不存在了
    这个不是叫做复制吧。这个应该是自动装箱的过程,在堆里面的新内存。

    打开Integer类,看valueOf(int)方法。所谓装箱,就是自动调用这个方法。所谓copy by value,就是复制了这个变量的值。
    Integer的确是在堆里面,那是因为它是一个对象,而它所封装的int是它的一个成员,也在堆里面。但是这个成员变量的值是哪里来的,是不是从i这个源头复制过来的呢?
    这位兄弟说的有道理!
    装箱的过程中,有一个值的拷贝的过程。
      

  18.   

    http://developer.51cto.com/art/201103/251163.htm
    这个例子很相似。
      

  19.   

    这里的i是local primitive variable,不存在别人对其的引用
    任意变量均会占用内存空间,为什么没有引用?难道凭空出来?
    作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。
    int a;
    if (....) {
      int i = 10;
      a = i;
    }
    假设变量a的内存地址是1000,i的内存地址是996
    出了if{...}之后,i就被销毁,a与i没有任何关系,除了它们的内存里的值相同,并不是a引用了i
    i是变量,不是内存,销毁的仅仅是i这个变量,而值还是在内存里面,如果这个地址没有被任何对象引用,那么才会在一定时间内被JVM回收。引用指的是引用地址,而不是谁引用谁,OK?

    这个10,应该是在栈里面还是在data segment中?
      

  20.   

    看这个 http://javabeezer.iteye.com/blog/634530
      

  21.   

    OH,你是这样子解释的。
    他们都是指向同一个内存空间~~~~
    所以只要这个内存空间变化了,他引用的值也会改变;
    而只要这个内存空间有引用,它就不会被JVM销毁,对吗?
      

  22.   

    以下是我的想法:
    1. i是局部变量,出了这个作用域,就会销毁局部变量;
    2. test()方法中,c.add(i)有自动装箱操作,装箱过程中copy i的值到对象里面作为成员变量;(虽然是个值传递,但是test()中的c与main函数中的c指向同一个内存地址, 所以main中的c也会发生改变)
    3. 如果有字面值,如10, 只要有引用存在,就不会被销毁;
      

  23.   

    OH,你是这样子解释的。
    他们都是指向同一个内存空间~~~~
    所以只要这个内存空间变化了,他引用的值也会改变;
    而只要这个内存空间有引用,它就不会被JVM销毁,对吗?
    像 int i = 10 这样的变量,不管是变量本身还是10常量,都是在栈里面的。如果用汇编语言写,i就只是一个由某个寄存器加减算出的地址,而10是一个常量,直接写入这个地址的位置。所以并没有什么对这种局部变量的引用一说,这个变量本身就是一个内存地址,10就是这个内存地址上的值。CPU通过对前面所说的那个寄存器的计算来获得这个地址,进而获得它的值。这才是栈的概念。即便是JVM,对于栈的管理应该也是类似的概念。不存在对局部变量的回收,只有销毁。而回收的是对于堆中的内存而言
      

  24.   

    看看值传递和引用传递吧,一般来说大部分引用数据类型都是用得引用传递,你可以把那个程序改成:public static void main(String[] args) {
        // TODO Auto-generated method stub
        int c = 10 ;
        test(c);
        System.out.println(c);
    }
    private static int test(int c) {
        // TODO Auto-generated method stub
       return c+1000;
    }
    试试这个程序看看运行效果.