今天我们来谈一谈java程序在内存之中的执行过程,掌握程序在内存中的执行过程是至关重要的,所以本人开始从简单的程序入手一点点解析内存中的程序是怎么执行的,废话不多说先上一段代码。
public class TestArray1{
/*
selectSorting
*/
public static void main(String[] args){
int[] a = new int[args.length];
for(int i=0;i<args.length;i++){
a[i] = Integer.parseInt(args[i]);
}
printSort(a);
selectSort(a);
printSort(a);
}
private static void selectSort(int[] a){
int k,temp;
for(int i=0;i<a.length;i++){
k = i;
for(int j=k+1;j<a.length;j++){
if(a[j]<a[k]){
k = j;
}
}
if(k != i){
temp = a[i];
a[i]=a[k];
a[k]=temp;
}
}
}
private static void printSort(int[] a){
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
System.out.println();
}
}
很简单的一段小程序,首先分析内存我们肯定是从main方法开始分析,那么接下来我们从main方法开始一句一句分析代码在内存之中的执行过程。首先看main方法第一句
int[] a = new int[args.length];
这句话很简单,我们new了一个新的数组然后这个数组的内容是args.length, 那么args.length是多长呢,首先我们要知道main方法中的String[] args这个数组是干什么用的,这个数组相当于是一个备用数组当我们在编译完程序之后在执行程序前输入的各个数据会被放到这个数组之中,如图所示:
我们在执行程序时在后面输入的各个数据将会被存入到这个数组里面中间那需要用空格隔开。那么我们接着分析内存:
我们这里new了一个新的数组这个时候内存之中的执行过程是,从栈空间里面分配一块空间a 这个a多大我不知道,我知道我通过这个a可以找到堆内存中的一个int数组并且它的长度是args.length
image.png
从图上我们可以明确的看到栈空间里面的一个a指向了堆空间里的一个int数组并且数组的长度是args.length,然后我们接着往下看代码执行
for(int i=0;i<args.length;i++){
a[i] = Integer.parseInt(args[i]);
}
我们这里走了一个for循环,我们可以看到我们这里将args这个数组里面存储的所有数据都放到了a这个数组里面,内存之中只是将a指向的这个数组装满了数据,相当于我们将一个空桶装满了水,然后我们接着看后面的执行,下面执行了printSort这个方法我们看printSort这个方法都做了哪些操作。
private static void printSort(int[] a){
for(int i=0;i<a.length;i++){
System.out.print(a[i]+" ");
}
System.out.println();
}
我们可以明确的看到printSort方法是将a数组里面的数据一一的输出出来。然后我们接着看selectSort这个方法,此程序的重点就在selectSort方法,selectSort方法主要是做了排序的操作,
private static void selectSort(int[] a){
int k,temp;
for(int i=0;i<a.length;i++){
k = i;
for(int j=k+1;j<a.length;j++){
if(a[j]<a[k]){
k = j;
}
}
if(k != i){
temp = a[i];
a[i]=a[k];
a[k]=temp;
}
}
}
我们就主要看看排序是怎么从内存之中执行的。首先我们看到selectSort方法第一步先定义了两个int类型的变量k,和temp并且没有赋值,如果我们没有赋值的话,那么java会自动设置默认值,int类型的默认值是0至于其他类型的可以自己去查询api文档这里不过多说,接下来我们看图说话:
image.png
我们可以看到,在栈空间中分配了两块内存k和temp并且初始值都是0.
程序接着向下执行
for(int i=0;i<a.length;i++){
k = i;
for(int j=k+1;j<a.length;j++){
if(a[j]<a[k]){
k = j;
}
}
if(k != i){
temp = a[i];
a[i]=a[k];
a[k]=temp;
}
}
这里执行了一个双重的for循环,双重循环或者是多重循环都是从里往外执行所以先执行里面的for循环在执行外面的for循环,首先是k=i
那么这里就是将i的值赋值给了k,接下来我们看里面的循环
for(int j=k+1;j<a.length;j++){
if(a[j]<a[k]){
k = j;
}
}
这里的j初始值是k+1就相当于当i=0时,j=1,当i=1,j=2以此类推
if(a[j]<a[k]){
k = j;
}
并且我们需要注意这里是将i的值赋值给了k所以此时k在栈空间里存储的值是i,然后这里a[j]和a[k]做了一个比较并且将下标值进行了更换。此时只是进行前一个值和后一个值进行比较经过此次的for循环我们可以知道这个数组之中最小数的下标值是多少,然后在进行和i的比较看看这个最小数的下标值是不是等于i如果等于i那么正好就不需要调换位置
if(k != i){
temp = a[i];
a[i]=a[k];
a[k]=temp;
}
如果这个最小值的下标值和i不相等那么我们就需要将这个最小值的下标值赋值给i这个位置,我们这里需要注意的是i也是下标值
当我们执行完这个循环之后此时的内存如下图所示:
image.png
这里的k和i都是下标值temp只不过是临时存储了a[i],因为当两个数调换位置的话我们不能直接赋值我们需要一个第三个的容器来存储其中的一个然后两个才能进行调换位置。当我们的for循环完全执行完之后此时的垃圾回收器将会马上回收temp和k 这两块内存此时的内存如下图
image.png
只剩下a指向堆内存中的int数组并且此时的int数组已经是从下到大排好序的所以此时selectSort方法执行完毕然后main方法在执行了printSort方法将排好序的数据进行一一打印。如图所示这就是我们最终的执行结果
image.png
首先上面先打印的没排好序的数组然后打印已经排好序的内容,基本上这段程序就执行完了,执行完之后垃圾回收器就会将这些内存都回收了,程序挺简单的主要就是内存分析
网友评论