java中对象作为参数,实际传递的是对象的引用(地址),但是我们还是称为值传递。因为传递的是引用(地址)的值。
首先来看Java中这三个变量在内存空间上的差别:
void function(){
int a=0;
Person p = new Person();
Person p0;
}
第一个变量在内存中开了一个内存块,而第二个变量在内存中有两个内存块。第三个开了一个内存块;
第一个就是在栈中开了一个int的内存。第二个要在堆中开一个内存块存储new Person()这个对象本身,还要再在栈中开一个引用类型的块 p 存储对象的堆地址。而我们对p的操作仅仅是操作了地址,而不是对对象的操作,对对象的操作都要有''."这个操作符。
所以函数/方法传参的时候都称为值传递,我们把一个对象引到另一个方法中操作的时候,传递的是对象的引用(地址)
当理解了Person p = new Person(); 中的变量p 和new Person 对象本身是两个东西之后,很多问题都是显而易见的。当对象作为参数时,虽然是值传递,但是仅新建了对象的引用这个变量,而不重新创建对象本身。
再说说String类型:
String a = "abc";//"abc"这个对象在常量池中有,则直接使用,没有则创建
String a= new String("abc");//"abc"这个对象在常量池中有,则直接使用,没有则创建
第一句实际上会用到二块内存块,一个引用变量a ,一个是"abc"这个对象,这个对象是放在常量池中的。
第二句会用到三个内存块,一个是应用变量,一个是"abc"常量池中的对象,最后一个是在堆内存中开的字符串对象,对象内容复制于"abc"。
本来在刷面试题,看到栈这个内容,想到还有个堆不知道是啥,搜索一下没看懂,就看到了内存区分类:堆,栈,静态,常量...,代码区。
然后就想到了c++中的malloc,百度一下,
1)malloc申请的都是堆内存,而申请栈内存就是函数/方法中定义局部基本类型的变量,比如int a =0; int[] a={0};
2)之所以经常用malloc申请内存,而不是定义变量。看了半天,觉得可能是栈内存比较小,堆内存比较大,所以想使用大数组就用malloc。
然后看着看着就想起来个一直以来的问题,变量名存储再哪?(当然变量名是不存储的,编译之后就没有了)我就又百度了一下。
就是C++语言中的:
1 )函数中 int a ; 这个语句与 int a=0; 这个语句,究竟在内存怎么存储的,有什么区别。当然,看了半天发现没有区别,都是在栈中开一个int大小的空间,只是一个里面存了0。另一个里面存的是随机值(没有初始化);
2)那如果有个class,class Person{.....}。这个类,在函数中 Person p;与Person * p=new Person();呢。Person p只是分配了一块内存。而Person *p=new Person();则是两块,一个是p的一个是new Person对象的。