目录
1.5.2.2 例子2
package com.qcby.内存图2;
public class Person {
public int age;
public String name;
public static int flag;
public void m1() {
}
public static void m2() {
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + ",flag="+flag+"]";
}
}
package com.qcby.内存图2;
public class Test {
public static void main(String[] args) {
Person x1 = new Person();
x1.age = 20;
x1.name = "张三";
x1.flag = 1;
Person x2 = new Person();
x2.age = 22;
x2.name = "李四";
x2.flag = 2;
System.out.println(x1);
System.out.println(x2);
change1(x1,x2);
System.out.println(x1);
System.out.println(x2);
change2(x1,x2);
System.out.println(x1);
System.out.println(x2);
}
public static void change1(Person a,Person b) {
Person temp = a;
a = b;
b = temp;
}
public static void change2(Person a,Person b) {
int temp_age = a.age;
String temp_name = a.name;
a.age = b.age;
a.name = b.name;
b.age = temp_age;
b.name = temp_name;
}
}
flag是2,是因为flag保存在静态常量池里(是静态变量),并且有且只有一个,创建对象,在堆中不会有flag。所有的对象都同时用一个flag。


1.5.2.3 例子3 - 一维数组
package com.qcby.内存图2;
public class Test1 {
public static void main(String[] args) {
int[] arr1 = {1,5,7,3};
//如果要修改,不可以arr1 = {7,9,10,15}
//因为数组是引用类型的数据,只可以改变属性,不可以改变里面的值
//因为语法限制,arr1 = {7,9,10,15}这种形式只限于数组初始化
//如果要修改数组的值有以下两种方式
//第一种:直接修改原数组的元素
//arr1[0] = 7;
//arr1[1] = 9;
//arr1[2] = 10;
//arr1[3] = 15;
//第二种:创建一个新的数组对象并将其引用赋值给arr1
arr1 = new int[]{7, 9, 10, 15};
int[] arr2 = arr1;
String[] arr3 = {"aa","bb",new String("cc")};
arr3[0] = "dd";
arr3[2] = "ee";
Person x1 = new Person();
Person[] arr4 = {x1,new Person(),new Person()};
}
}
Person类用的是例子2的Person类。
数组只有数组名才算变量,arr1[0]这种不是,这种只能算访问数组里面元素的方法。

不被指向就被回收。

继续。对于数组,如果是基本数据类型就直接在框里面写;如果是String,就按String的方式开辟;如果是new,就在堆中重新开辟一个空间。
对于下面这行代码,arr3[0]和arr3[1]会在字符串常量池开辟空间,因为他等效于用等号定义。
String[] arr3 = {"aa","bb",new String("cc")};

字符串常量池里的数据只有满了才会被回收。其他都是不被指向就回收。

继续。


1.5.2.4 例子4 - 二/三维数组
package com.qcby.内存图2;
public class Test1 {
public static void main(String[] args) {
int[][] arr= {{1,2},{7,4,6},{1,8,9}};
int[][] arr2 = new int[3][2];//3个一维数组,每个一维数组有2个数
arr2[1] = new int[] {4,8,9,10};
String[][] arr3 = {{"aa","bb"},{"cc",new String("dd")},{new String("ee")}};
arr3[0] = new String[] {"xxxx"};
arr3[2][0] = new String("yyyyy");
Person x1 = new Person();
Person x2 = new Person();
Person[][] arr4 = {{x1,x2},{new Person()}};
int[][][] arr5 = {{{1},{1,2}},{{3,4},{5}}};
}
}
数组画内存图,一维一维的画。


继续。不被指向的就被回收,字符串常量池满了才回收不被指向的。

继续。

继续。

1.5.3 几个概念
几个概念(是画内存图没有涉及的,下面的描述参考例子2):
进程:从main方法入栈(确切来说是在栈区里面的线程栈,图上没有画)开始,在里面执行的一系列过程(change1和change2的出栈和入栈)。即依托栈结构执行的一系列方法叫进程。
进程在内存中独占一块空间,相互之间不会打扰,每一个进程都会有自己的主方法,可以通过自己的main方法调用起来。
线程:依托一个进程里面的main方法,开辟了多个线程栈,此时,每一个线程栈里执行的一系列过程就叫一个线程。

程序计数器:记录程序执行状态(比如:程序执行到了哪里、执行到什么状态、什么时候开始执行、什么时候结束执行)
本地方法栈:把Java编译成的c(这个c是Java自定义的c,没有办法直接去调驱动),转换成操作系统能够识别的c(操作系统底层用到的都是c,因为各个硬件的接口是靠c语言写的)。
14万+

被折叠的 条评论
为什么被折叠?



