先上一段代码
public class SimpleTest {
String str ="good";
char[] ch = {'a','b','c'};
public void change(String str,char ch[]){
str = "test ok";
ch[0] = 'g';
}
public static void main(String[] args) {
SimpleTest st = new SimpleTest();
st.change(st.str, st.ch);
System.out.print(st.str + " and ");
System.out.print(st.ch);
}
}
PS: 字符串一旦创建,便不可修改
PPS: JVM内存可分为三个区,堆(Heap),栈(Stack),方法区(Method)
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
这段代码都做了些什么
1.启动一个JVM进程,首先从classpath找到SimpleTest.class文件,读取文件中的二进制数据,然后把SimpleTest类的类信息存放在运行时数据区的方法区中,这一过程称为SimpleTest的类加载过程
2.JVM定位到方法区中SimpleTest类的main()方法的字节码,开始执行它的指令。第一条语句是:
SimpleTest st = new SimpleTest();
语句很简单啦,就是让JVM创建一个SimpleTest实例,并且,使引用变量st来引用这个实例。看起来是小事一桩,具体JVM是怎么执行的呢?
1> 不就是建立一个SimpleTest实力吗?JVM直奔方法区,先找到SimpleTest类的类信息再说。结果呢//木有@_@,这会儿的方法区内还没有SimpleTest类。可JVM也不蠢...“自己动手,丰衣足食”,立马加载了SimpleTest类,并把类信息存放在方法区里。
2>类信息有了,JVM第一件事就是在堆内为一个新的SimpleTest实例分配内存,这个SimpleTest实例持有着指向方法区中的内存地址,这个地址,就存放在了SimpleTest实力的数据区。
3>在JVM进程中,每个进程都会拥有一个方法调用栈,用来跟踪线程运行中一系列的方法调用过程,栈中的每一个元素就被称为栈帧,每当线程调用一个方法的时候就会向方法栈压入一个新帧,用来存储方法的参数,局部变量和运算过程中的临时数据。位于“=”前的st是一个在main()方法中定义的变量,可见他是一个局部变量,因此它会被添加到执行了main()方法的主线程的JAVA方法调用栈中。而“=”将把这个st变量指向堆区中的SimpleTest实例,也就是说,它持有指向SimpleTest实例的引用。
到这里,第一条语句就执行完了。
3.接着就是调用st引用的对象的change方法,并把st所引用的字符串str和字符数组ch传入change方法,以一个新帧被压入change()方法所在的主线程的栈区。
4.在change()方法所在的栈区,st.str被要求引用"test ok"所在内存的地址,注意到上面提及的,“字符串一旦创建,便不可修改”,便是在main()方法所在的栈区内,st.str始终是引用了"good"所在的地址,在change()方法所在的栈区内,想改变st.str的引用为"test ok",实际上是重新开辟了另一块内存存放"test ok",并将此时的st.str暂时指向"test ok",我们可以在两处str和ch分别输出他们的hashcode。
引用变量时,除了8个基本类型外(byte,short,int,long,float,double,char,boolean),都是传递的内存地址,包括数组。所以这里的char数组ch[],是st.ch所开辟出来的内存地址,被要求ch[0]重新指向字符'g'。
到此,change()方法结束。
5.回到main()方法,st.str仍然指向"good",但ch[0]指向了'g'。
输出 good and gbc
jvm.pngJava没有按引用传递,全部是按值传递,传的是内存地址
网友评论