Java SE 学习---内存管理&函数参数传递,javase---内存管理
分享于 点击 5919 次 点评:83
Java SE 学习---内存管理&函数参数传递,javase---内存管理
- Java的内存管理
Java虚拟机管理的存储空间在逻辑上可以分为两个区域:1)栈区域 2)堆区域。在这两个区域上存储的数据也不一样
具体情况下面举例说明:
public class Student {
String stuId;
String stuName;
int stuAge;
}
public class TestStudent {
public static void main(String[] args) {
Student zhouxingxing = new Student();
String name = new String("旺旺");
int a = 10;
char b = 'm';
zhouxingxing.stuId = "9527";
zhouxingxing.stuName = "周星星";
zhouxingxing.stuAge = 25;
}
}
在上面的代码中 Student zhouxingxing = new Student();
定义了一个指向Student的引用类型变量zhouxingxing并将它的值设为new Student()对象在堆中的首地址
String name = new String("旺旺");
同样指向String的引用类型变量name的值设为对象 new String("旺旺")在堆中的首地址
int a = 10; char b = 'm';
a和b为基本类型的变量他们的存储空间位于栈区,他们存储在为其分配的空间的内容就是他们的值。
下图是上述例子的内存分布图:
引用类型中的数组也封装了指针,即便是基本数据类型的数组也封装了指针,数组也是引用类型。比如代码int[] arr = new int[]{23,2,4,3,1};如下图所示:
- Java的函数的参数传递
关于Java的函数的参数传递的问题,有人认为Java调用方法时向方法传递的是变量的值,有人认为传递的是引用(即指针)。其实我认为这两种说法都有理,引用类型的变量存的其实就是一个对象或者数组的地址(本质上也使用几个字节的空间存储的数值)这和基本类型的变量存储的值没有什么区别只是表示的含义不一样而已,因此我们可以认为Java的参数传递方式是“值”传递,说是引用传递也说得过去,因为在Java中自定义类型变量的使用频率远远超出了基本类型的变量,只不过基本类型的变量的值是一种特殊的“引用”它并不是指向堆中某一块存储区域的地址而就是其要表示的数值本身。
举一个例子:
class A{
...
}
void method(A param){
...
}
void method(int param){
...
}
A a=new A();
int test=12;
method(a);
method(test);
当调用method(A param)时,A类型的实参a将指向的对象的地址传递给形参,在方法method(A param)中对形参的修改(这里的修改指的是对其指向的堆空间的对象数据的修改)都会改变实参指向的空间的值。而当调用method(int param)时形参(基本类型的变量int test)将自己的值传递给形参,形参会在栈中拷贝一份实参的值,在方法内部对形参的修改将不会对实参的值造成任何的影响。
关于Java的参数传递有一个特殊的情况,就是传递String类型的变量时,形参的改变并不会对实参造成改变
例如:
public class TestString {
public static void main(String[] args) {
String name = "wangwang";
TestString testString = new TestString();
System.out.println("方法调用前:" + name);
testString.change(name);
System.out.println("方法调用后:" + name);
}
void change(String str) {
str = "旺旺老师";
System.out.println("方法体内修改值后:" + str);
}
}
结果:
方法调用前:wangwang
方法体内修改值后:旺旺老师
方法调用后:wangwang
分析:我们看初始情况,即String name = "wangwang";这行代码运行
完,如下图:
当调用方法时testString.change(name),内存变化为:
在方法体内,参数str赋予一个新值,str = "旺旺老师"。由于String是final类型的对象一经创建之后就不允许对其进行修改,当然就不会允许将str(地址为36DF)的空间的值设置为“旺旺老师”,在这种情况下系统就会在堆中分配一块新的内存空间37DF并将37DF这块内存区域的值设置为“旺旺老师”,并将str指向这块内存区域,而name还是指向36DF, 37DF的改变对它已没影响:
最后,方法调用结束,str与37DF的内存空间消亡。Name的值依然为wangwang,并没有改变。 所以String虽然是引用类型参数,但值依然不变:
关于String类型更多的分析见这篇blog
最后是一个综合的例子:
public class TestChange {
void change(Student stu1, Student stu2) {
stu1.stuAge ++;
stu2.stuAge ++;
Student stu = stu1;
stu1 = stu2;
stu2 = stu;
}
public static void main(String[] args) {
Student furong = new Student();
furong.stuName = "芙蓉姐姐";
furong.stuAge = 30;
Student fengjie = new Student();
fengjie.stuName = "凤姐";
fengjie.stuAge = 26;
TestChange testChange = new TestChange();
testChange.change(furong, fengjie);
System.out.println(furong.stuName);
System.out.println(furong.stuAge);
System.out.println(fengjie.stuName);
System.out.println(fengjie.stuAge);
}
}
运行结果:
芙蓉姐姐
31
凤姐
27
分析:
相关文章
- 暂无相关文章
用户点评