栈:
描述Java方法执行的内存模型,每个方法被执行的时候都会同时创建一个栈帧用于存储局部变量、操作栈、动态链接、方法出口等信息。
每一个方法,创建一个栈帧,栈帧存放了当前就方法的数据信息(局部变量),当方法调用完毕,该方法的栈帧就被销毁。
堆:
被所有线程共享的一块内存区域,在虚拟机启动时创建。所有的对象实例以及数组都要在堆上分配,使用new关键字,就表示在堆中开辟一块新的存储空间
方法区:
线程共享的内存区域,存储已被虚拟机加载的类信息、常量池、static变量等。
———————————————————————————————————————————————————————————————————————
Java值传递机制——基本数据类型
package com.mipo.javase.reference;
/**
* 方法参数的值传递机制之基本数据类型
* 结论:
* 如果参数类型是基本数据类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值。
* 如果在函数中改变了副本的值,原始的值不会改变
* @author Administrator
*
*/
public class ParameterDemo1 {
//每个方法执行时,都会创建一个栈帧,栈帧存放了当前方法的数据信息(局部变量、方法参数)
//在栈空间中创建main方法的栈帧
public static void main(String[] args) {
//main方法的栈帧中开辟一块内存空间,存放 x=10
int x = 10;
//打印结果10
System.out.println("main方法前:"+x);
//在栈空间中创建change方法的栈帧,此时该栈帧位于栈顶,谁在栈顶就执行谁
//把x的值拷贝一份,再传递给change()方法的x变量(传递仅仅是数值10)
change(x);
//当change()方法调用完毕后,它就会出栈;main方法又回到栈顶,谁在栈顶就执行谁
//在main方法的栈帧里,x=10
//打印结果10
System.out.println("main方法后:"+x);
}
static void change(int x) {
//change()方法的栈帧中开辟一块内存空间,存放形参x
//打印结果10
System.out.println("change方法前:"+x);
//把50赋值给了change()方法中的变量x
x = 50;
//打印结果50
System.out.println("change方法后:"+x);
}
}
从JVM内存角度分析
Java值传递机制——引用数据类型
package com.mipo.javase.reference;
/**
* 方法参数的值传递机制之引用数据类型
* 结论:
* 如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址值。
* 如果在函数中没有改变这个副本的地址,而是改变了地址中的内容,那么在函数内的改变会影响到传入的参数。
* 如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的地址,所以不会改变参数的值。
* @author Administrator
*
*/
public class ParameterDemo2 {
//每个方法执行时,都会创建一个栈帧,栈帧存放了当前方法的数据信息(局部变量、方法参数)
//在栈空间中创建main方法的栈帧
public static void main(String[] args) {
//栈区的arr引用的是堆空间的new对象
int[] arr = new int[]{10,99,101} ;
//打印结果10,99,101
System.out.println("main方法前:"+arr[0]+","+arr[1]+","+arr[2]);
//在栈空间中创建change方法的栈帧,此时该栈帧位于栈顶,谁在栈顶就执行谁
//把main方法中的arr所引用的地址值:0x342f(十六进制表示)复制一份,把复制之后的副本传递给change方法的arr变量
change(arr);
//当change()方法调用完毕后,它就会出栈;main方法又回到栈顶,谁在栈顶就执行谁
//由于main()方法和change()方法操作的是堆空间的同一地址,此时arr的值改了
//打印结果55,99,101
System.out.println("main方法后:"+arr[0]+","+arr[1]+","+arr[2]);
}
static void change(int[] arr) {
//change()方法的栈帧中开辟一块内存空间,存放形参x
//打印结果10,99,101
System.out.println("change方法前:"+arr[0]+","+arr[1]+","+arr[2]);
//把堆空间的arr[0]更改为55
arr[0] = 55;
//打印结果55,99,101
System.out.println("change方法后:"+arr[0]+","+arr[1]+","+arr[2]);
}
}
从JVM内存角度分析
package com.mipo.javase.reference;
/**
* 方法参数的值传递机制之引用数据类型
* 结论:
* 如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址值。
* 如果在函数中没有改变这个副本的地址,而是改变了地址中的内容,那么在函数内的改变会影响到传入的参数。
* 如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的地址,所以不会改变参数的值。
* @author Administrator
*
*/
public class ParameterDemo2 {
//每个方法执行时,都会创建一个栈帧,栈帧存放了当前方法的数据信息(局部变量、方法参数)
//在栈空间中创建main方法的栈帧
public static void main(String[] args) {
//栈区的arr引用的是堆空间的new对象
int[] arr = new int[]{10,99,101} ;
//打印结果10,99,101
System.out.println("main方法前:"+arr[0]+","+arr[1]+","+arr[2]);
//在栈空间中创建change方法的栈帧,此时该栈帧位于栈顶,谁在栈顶就执行谁
//把main方法中的arr所引用的地址值:0x342f(十六进制表示)复制一份,把复制之后的副本传递给change方法的arr变量
change(arr);
//当change()方法调用完毕后,它就会出栈;main方法又回到栈顶,谁在栈顶就执行谁
//由于main()方法和change()方法操作的是堆空间的同一地址,此时arr的值改了
//打印结果10,99,101
System.out.println("main方法后:"+arr[0]+","+arr[1]+","+arr[2]);
}
static void change(int[] arr) {
//change()方法的栈帧中开辟一块内存空间,存放形参x
//在堆中又创建一个对象arr,把main()方法中传递过来的地址值改为新的地址值
arr = new int[]{20,99,101};
//打印结果20,99,101
System.out.println("change方法前:"+arr[0]+","+arr[1]+","+arr[2]);
//把堆空间的arr[0]更改为55
arr[0] = 55;
//打印结果55,99,101
System.out.println("change方法后:"+arr[0]+","+arr[1]+","+arr[2]);
}
}