关于作用域和集合的一点疑问

SRCIsGrowing 2013-05-10 10:39:52
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,希望大神们前来解释^^
...全文
247 31 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
JPF1024 2013-05-11
  • 打赏
  • 举报
回复
看看值传递和引用传递吧,一般来说大部分引用数据类型都是用得引用传递,你可以把那个程序改成:

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;
}
试试这个程序看看运行效果.
SRCIsGrowing 2013-05-10
  • 打赏
  • 举报
回复
引用 1 楼 woshinigeno1 的回复:
参数传递传的是Collection 的引用
嗯,是的。但是i脱离了这个函数test()后,为什么在c中还有值啊?
woshinigeno1 2013-05-10
  • 打赏
  • 举报
回复
参数传递传的是Collection 的引用
lcf 2013-05-10
  • 打赏
  • 举报
回复
引用 25 楼 sjkzc3 的回复:
[quote=引用 22 楼 fsh2008 的回复:] http://developer.51cto.com/art/201103/251163.htm 这个例子很相似。
OH,你是这样子解释的。 他们都是指向同一个内存空间~~~~ 所以只要这个内存空间变化了,他引用的值也会改变; 而只要这个内存空间有引用,它就不会被JVM销毁,对吗?[/quote]
引用 27 楼 sjkzc3 的回复:
以下是我的想法: 1. i是局部变量,出了这个作用域,就会销毁局部变量; 2. test()方法中,c.add(i)有自动装箱操作,装箱过程中copy i的值到对象里面作为成员变量;(虽然是个值传递,但是test()中的c与main函数中的c指向同一个内存地址, 所以main中的c也会发生改变) 3. 如果有字面值,如10, 只要有引用存在,就不会被销毁;
像 int i = 10 这样的变量,不管是变量本身还是10常量,都是在栈里面的。如果用汇编语言写,i就只是一个由某个寄存器加减算出的地址,而10是一个常量,直接写入这个地址的位置。所以并没有什么对这种局部变量的引用一说,这个变量本身就是一个内存地址,10就是这个内存地址上的值。CPU通过对前面所说的那个寄存器的计算来获得这个地址,进而获得它的值。这才是栈的概念。 即便是JVM,对于栈的管理应该也是类似的概念。不存在对局部变量的回收,只有销毁。而回收的是对于堆中的内存而言
这个用户很懒 2013-05-10
  • 打赏
  • 举报
回复
引用 3 楼 wandefajin 的回复:
两个变量操作的是一个对象,就像你和你朋友共用一台电脑,当他下载一个游戏之后,你玩的时候电脑上就有那个游戏了
好耐性!
SRCIsGrowing 2013-05-10
  • 打赏
  • 举报
回复
引用 26 楼 xianwangkai 的回复:
引用的问题!添加的是引用!
过程没有那么简单
SRCIsGrowing 2013-05-10
  • 打赏
  • 举报
回复
以下是我的想法: 1. i是局部变量,出了这个作用域,就会销毁局部变量; 2. test()方法中,c.add(i)有自动装箱操作,装箱过程中copy i的值到对象里面作为成员变量;(虽然是个值传递,但是test()中的c与main函数中的c指向同一个内存地址, 所以main中的c也会发生改变) 3. 如果有字面值,如10, 只要有引用存在,就不会被销毁;
xianwangkai 2013-05-10
  • 打赏
  • 举报
回复
引用的问题!添加的是引用!
SRCIsGrowing 2013-05-10
  • 打赏
  • 举报
回复
引用 22 楼 fsh2008 的回复:
http://developer.51cto.com/art/201103/251163.htm 这个例子很相似。
OH,你是这样子解释的。 他们都是指向同一个内存空间~~~~ 所以只要这个内存空间变化了,他引用的值也会改变; 而只要这个内存空间有引用,它就不会被JVM销毁,对吗?
lcf 2013-05-10
  • 打赏
  • 举报
回复
SRCIsGrowing 2013-05-10
  • 打赏
  • 举报
回复
引用 20 楼 fsh2008 的回复:
[quote=引用 16 楼 lcf 的回复:] [quote=引用 12 楼 fsh2008 的回复:] [quote=引用 10 楼 lcf 的回复:] [quote=引用 9 楼 fsh2008 的回复:] int i=100; c.add(i); 个人认为,这儿add的是i的引用(如果是一个对象,更容易理解一些),结束test方法后,虽然作用域不在了,但是内存里面i的引用还是在的,而因为collection还在使用这个引用,也不会对其进行回收。
这里的i是local primitive variable,不存在别人对其的引用 [/quote] 任意变量均会占用内存空间,为什么没有引用?难道凭空出来? 作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。[/quote] int a; if (....) { int i = 10; a = i; } 假设变量a的内存地址是1000,i的内存地址是996 出了if{...}之后,i就被销毁,a与i没有任何关系,除了它们的内存里的值相同,并不是a引用了i [/quote] i是变量,不是内存,销毁的仅仅是i这个变量,而值还是在内存里面,如果这个地址没有被任何对象引用,那么才会在一定时间内被JVM回收。引用指的是引用地址,而不是谁引用谁,OK? [/quote] 这个10,应该是在栈里面还是在data segment中?
fsh2008 2013-05-10
  • 打赏
  • 举报
回复
http://developer.51cto.com/art/201103/251163.htm 这个例子很相似。
SRCIsGrowing 2013-05-10
  • 打赏
  • 举报
回复
引用 18 楼 lcf 的回复:
[quote=引用 15 楼 sjkzc3 的回复:] [quote=引用 7 楼 lcf 的回复:] [quote=引用 5 楼 sjkzc3 的回复:] [quote=引用 4 楼 lcf 的回复:] 因为i的值被复制进了ArrayList。
这个解释不专业。 我自己给一个解释: 1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。 2. 当test()调用完毕后,i 这个变量自动销毁。 你看这个解释如何? 但是,不知道如何验证?[/quote] 即便是装箱,i也是被复制过一次。至于是否销毁,这个无法验证,因为编译器阻止你在变量的作用范围之外引用它。你只能反问,为什么编译器要这么做?答案只能是,那个变量已经不存在了[/quote] 这个不是叫做复制吧。这个应该是自动装箱的过程,在堆里面的新内存。 [/quote] 打开Integer类,看valueOf(int)方法。所谓装箱,就是自动调用这个方法。所谓copy by value,就是复制了这个变量的值。 Integer的确是在堆里面,那是因为它是一个对象,而它所封装的int是它的一个成员,也在堆里面。但是这个成员变量的值是哪里来的,是不是从i这个源头复制过来的呢?[/quote] 这位兄弟说的有道理! 装箱的过程中,有一个值的拷贝的过程。
fsh2008 2013-05-10
  • 打赏
  • 举报
回复
引用 16 楼 lcf 的回复:
[quote=引用 12 楼 fsh2008 的回复:] [quote=引用 10 楼 lcf 的回复:] [quote=引用 9 楼 fsh2008 的回复:] int i=100; c.add(i); 个人认为,这儿add的是i的引用(如果是一个对象,更容易理解一些),结束test方法后,虽然作用域不在了,但是内存里面i的引用还是在的,而因为collection还在使用这个引用,也不会对其进行回收。
这里的i是local primitive variable,不存在别人对其的引用 [/quote] 任意变量均会占用内存空间,为什么没有引用?难道凭空出来? 作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。[/quote] int a; if (....) { int i = 10; a = i; } 假设变量a的内存地址是1000,i的内存地址是996 出了if{...}之后,i就被销毁,a与i没有任何关系,除了它们的内存里的值相同,并不是a引用了i [/quote] i是变量,不是内存,销毁的仅仅是i这个变量,而值还是在内存里面,如果这个地址没有被任何对象引用,那么才会在一定时间内被JVM回收。引用指的是引用地址,而不是谁引用谁,OK?
lcf 2013-05-10
  • 打赏
  • 举报
回复
引用 17 楼 sjkzc3 的回复:
[quote=引用 8 楼 lcf 的回复:] 好吧如果i在byte的取值范围之内它就不是复制,不过这个也属于细节。假设i的值是1000好了
你的意思是 i 是 byte 类型吗?[/quote] 自动装箱过程,去看Integer.valueOf(int)的源代码。如果i在byte的取值范围之内,装箱的结果是预先建立好的Integer对象,对象中封装的成员变量的值并不是直接从i处得来
lcf 2013-05-10
  • 打赏
  • 举报
回复
引用 15 楼 sjkzc3 的回复:
[quote=引用 7 楼 lcf 的回复:] [quote=引用 5 楼 sjkzc3 的回复:] [quote=引用 4 楼 lcf 的回复:] 因为i的值被复制进了ArrayList。
这个解释不专业。 我自己给一个解释: 1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。 2. 当test()调用完毕后,i 这个变量自动销毁。 你看这个解释如何? 但是,不知道如何验证?[/quote] 即便是装箱,i也是被复制过一次。至于是否销毁,这个无法验证,因为编译器阻止你在变量的作用范围之外引用它。你只能反问,为什么编译器要这么做?答案只能是,那个变量已经不存在了[/quote] 这个不是叫做复制吧。这个应该是自动装箱的过程,在堆里面的新内存。 [/quote] 打开Integer类,看valueOf(int)方法。所谓装箱,就是自动调用这个方法。所谓copy by value,就是复制了这个变量的值。 Integer的确是在堆里面,那是因为它是一个对象,而它所封装的int是它的一个成员,也在堆里面。但是这个成员变量的值是哪里来的,是不是从i这个源头复制过来的呢?
SRCIsGrowing 2013-05-10
  • 打赏
  • 举报
回复
引用 8 楼 lcf 的回复:
好吧如果i在byte的取值范围之内它就不是复制,不过这个也属于细节。假设i的值是1000好了
你的意思是 i 是 byte 类型吗?
lcf 2013-05-10
  • 打赏
  • 举报
回复
引用 12 楼 fsh2008 的回复:
[quote=引用 10 楼 lcf 的回复:] [quote=引用 9 楼 fsh2008 的回复:] int i=100; c.add(i); 个人认为,这儿add的是i的引用(如果是一个对象,更容易理解一些),结束test方法后,虽然作用域不在了,但是内存里面i的引用还是在的,而因为collection还在使用这个引用,也不会对其进行回收。
这里的i是local primitive variable,不存在别人对其的引用 [/quote] 任意变量均会占用内存空间,为什么没有引用?难道凭空出来? 作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。[/quote] int a; if (....) { int i = 10; a = i; } 假设变量a的内存地址是1000,i的内存地址是996 出了if{...}之后,i就被销毁,a与i没有任何关系,除了它们的内存里的值相同,并不是a引用了i
SRCIsGrowing 2013-05-10
  • 打赏
  • 举报
回复
引用 7 楼 lcf 的回复:
[quote=引用 5 楼 sjkzc3 的回复:] [quote=引用 4 楼 lcf 的回复:] 因为i的值被复制进了ArrayList。
这个解释不专业。 我自己给一个解释: 1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。 2. 当test()调用完毕后,i 这个变量自动销毁。 你看这个解释如何? 但是,不知道如何验证?[/quote] 即便是装箱,i也是被复制过一次。至于是否销毁,这个无法验证,因为编译器阻止你在变量的作用范围之外引用它。你只能反问,为什么编译器要这么做?答案只能是,那个变量已经不存在了[/quote] 这个不是叫做复制吧。这个应该是自动装箱的过程,在堆里面的新内存。
wandefajin 2013-05-10
  • 打赏
  • 举报
回复
坐等结贴 接分!!!
加载更多回复(11)

62,634

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧