看了很多关于java中方法参数传递的文章,有说是按值传递的也有说是按引用传递,对于大部分开发人员来说可能对java运行过程中的内存机制不是非常了解,个人总结了一些关于该问题的理解与经验,供大家参考讨论。
个人理解:java中不管是基本类型还是普通java对象作为参数传递时,传递的都是“目标的拷贝”,那么如何理解目标呢,对于基本类型传递的应该是“值”,对于普通java对象来说传递的是“对象的引用”。
实例:
<span style="font-size:14px;">public class TestParam {
private void test1(int a){
a=100;
System.out.println("方法中a的值是:"+a);
}
private void test2(InnerClass b){
b.i=100;
}
private void test3(InnerClass b){
b=new InnerClass();
b.i=1000;
}
public static void main(String[] args) {
TestParam t = new TestParam();
int a = 3;
t.test1(a);
System.out.println("test1传入a执行后main方法中a的值依然为 "+a+" 并没有变成100");
InnerClass ic=t.new InnerClass();
t.test2(ic);
System.out.println("test2传入InnerClass实例 ic对象后,main方法中ic的成员变量i的值为 "+ic.i+" 注意:变成100了");
t.test3(ic);
System.out.println("test3传入InnerClass实例 ic对象后,new了一个InnerClass实例,main方法中ic的成员变量i的值为 "+ic.i+" 注意:并未变成1000");
}
class InnerClass{
int i=0;
}
}</span>
思考test1方法,因为a是基本类型,传递的值的copy,在方法体中,该copy被重新赋值为100了,但是这并不影响main方法中a的值;
思考test2方法,因为ic是一个普通的java对象,传递的是ic这个引用的copy,也就是在内存栈中保存了两个引用指向同一个堆中的实例,在方法体中,该引用把堆中实例的成员变量i改 为100了,那么对于main方法中的"ic"引用指向的同一个实例的成员变量i的值也改为100了。
思考test3方法,同理test2方法,传递的是ic这个引用的copy,也就是在内存栈中保存了两个引用指向同一个堆中的实例,但在方法体中,又在堆中重新new了一个对象实例指向该copy引用,那么这两个引用指向的实例就完全不相干了,也就也已理解main方法中的"ic"引用指向的同一个实例的成员变量i的值依然为100。
我发现对于同一个事实的理解有千百种,但是真相只有一个,这是不是一个基本的真相,我也不敢确定。其实最重要的是要有自己的理解。不要人云亦云,包括很多出版物上写的也不一定是对的。特别是关于java内存机制、类加载机制等。
举一个例子,对于上面的例子,“int a = 3;”在不同的地方声明 它的内存机制是什么样的呢?如何分析?看到过一些帖子说一定是在栈中,在方法体中声明,作为类的内部成员变量声明和作为类的静态成员变量声明真的都是在栈中吗?