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
// 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. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。
2. 当test()调用完毕后,i 这个变量自动销毁。
你看这个解释如何?
但是,不知道如何验证?
我自己给一个解释:
1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。
2. 当test()调用完毕后,i 这个变量自动销毁。
你看这个解释如何?
但是,不知道如何验证?
即便是装箱,i也是被复制过一次。至于是否销毁,这个无法验证,因为编译器阻止你在变量的作用范围之外引用它。你只能反问,为什么编译器要这么做?答案只能是,那个变量已经不存在了
c.add(i);
个人认为,这儿add的是i的引用(如果是一个对象,更容易理解一些),结束test方法后,虽然作用域不在了,但是内存里面i的引用还是在的,而因为collection还在使用这个引用,也不会对其进行回收。
至于变量i 因为局部变量都是在栈上的,当作用域也就是大括号被执行完之后,就会在内存中消失掉另外,第一次画图,效果不是很好,不好意思!!!
任意变量均会占用内存空间,为什么没有引用?难道凭空出来?
作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。
我自己给一个解释:
1. 这一行c.add(i),这里i是一个装箱的过程,也就说说new Integer(i),这个new出来的对象放在了堆里面,同时c进入了集合c,因此在出了test作用域之后,c中有这个对象的(new integer(i))。
2. 当test()调用完毕后,i 这个变量自动销毁。
你看这个解释如何?
但是,不知道如何验证?
即便是装箱,i也是被复制过一次。至于是否销毁,这个无法验证,因为编译器阻止你在变量的作用范围之外引用它。你只能反问,为什么编译器要这么做?答案只能是,那个变量已经不存在了
这个不是叫做复制吧。这个应该是自动装箱的过程,在堆里面的新内存。
任意变量均会占用内存空间,为什么没有引用?难道凭空出来?
作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。
int a;
if (....) {
int i = 10;
a = i;
}
假设变量a的内存地址是1000,i的内存地址是996
出了if{...}之后,i就被销毁,a与i没有任何关系,除了它们的内存里的值相同,并不是a引用了i
你的意思是 i 是 byte 类型吗?
我自己给一个解释:
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这个源头复制过来的呢?
你的意思是 i 是 byte 类型吗?
自动装箱过程,去看Integer.valueOf(int)的源代码。如果i在byte的取值范围之内,装箱的结果是预先建立好的Integer对象,对象中封装的成员变量的值并不是直接从i处得来
任意变量均会占用内存空间,为什么没有引用?难道凭空出来?
作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。
int a;
if (....) {
int i = 10;
a = i;
}
假设变量a的内存地址是1000,i的内存地址是996
出了if{...}之后,i就被销毁,a与i没有任何关系,除了它们的内存里的值相同,并不是a引用了i
i是变量,不是内存,销毁的仅仅是i这个变量,而值还是在内存里面,如果这个地址没有被任何对象引用,那么才会在一定时间内被JVM回收。引用指的是引用地址,而不是谁引用谁,OK?
我自己给一个解释:
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这个源头复制过来的呢?
这位兄弟说的有道理!
装箱的过程中,有一个值的拷贝的过程。
这个例子很相似。
任意变量均会占用内存空间,为什么没有引用?难道凭空出来?
作用域仅仅是针对变量,而变量仅仅是一个表示符号而已。
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中?
他们都是指向同一个内存空间~~~~
所以只要这个内存空间变化了,他引用的值也会改变;
而只要这个内存空间有引用,它就不会被JVM销毁,对吗?
1. i是局部变量,出了这个作用域,就会销毁局部变量;
2. test()方法中,c.add(i)有自动装箱操作,装箱过程中copy i的值到对象里面作为成员变量;(虽然是个值传递,但是test()中的c与main函数中的c指向同一个内存地址, 所以main中的c也会发生改变)
3. 如果有字面值,如10, 只要有引用存在,就不会被销毁;
他们都是指向同一个内存空间~~~~
所以只要这个内存空间变化了,他引用的值也会改变;
而只要这个内存空间有引用,它就不会被JVM销毁,对吗?
像 int i = 10 这样的变量,不管是变量本身还是10常量,都是在栈里面的。如果用汇编语言写,i就只是一个由某个寄存器加减算出的地址,而10是一个常量,直接写入这个地址的位置。所以并没有什么对这种局部变量的引用一说,这个变量本身就是一个内存地址,10就是这个内存地址上的值。CPU通过对前面所说的那个寄存器的计算来获得这个地址,进而获得它的值。这才是栈的概念。即便是JVM,对于栈的管理应该也是类似的概念。不存在对局部变量的回收,只有销毁。而回收的是对于堆中的内存而言
// 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;
}
试试这个程序看看运行效果.