数组的引用变量和内存分配

数组是一种引用类型,数组用来存储同一种数据类型的数据,一旦初始化完成,即所占的空间就已固定下来,即使某个元素被清空,但其所在空间仍然保留,因此数组长度将不能被改变。

数组变量只有分配内存空间后才可以使用。

数组初始化分为静态初始化(在定义时就指定数组元素的值,此时不能指定数组长度,否则就出现了静态加动态混搭初始化数组了)

动态初始化(只指定数组长度,由系统分配初始值,初始值根据定义的数据类型来)。

不要出现静态初始化跟动态初始化混搭比如new int[4]{1,3,4,5}

public class TestDemo {

    public static void main(String[] args) {
        //动态初始化
        int[] numbers = new int[4];
        numbers[0] = 1;
        for (int i : numbers) {
            System.out.println(i);
        }
        System.out.println("---------------");
        //静态初始化
        numbers = new int[] {1,2,3,6};
        for (int i : numbers) {
            System.out.println(i);
        }
    }
}

数组引用变量是存放在栈内存(stack)中,数组元素是存放在堆内存(heap)中,通过栈内存中的指针指向对应元素的在堆内存中的位置来实现访问,以下图来说明数组此时的存放形式。

栈内存存放的是方法的内部定义的变量,当方法执行完成后,栈内存也就随之消亡。而堆内存存放的一般是运行时的数据区以及创建一个对象的时候,对象是保存在堆内存,以便反复利用。当栈内存没用引用变量引用该数据区的数据时,垃圾回收就会合适时间来回收。

package com.eminem.vo;
public class TestDemo {

    public static void main(String[] args) {
        int[] numbers = {3,4,5};

        int[] digits = new int[4];

        //把numbers的引用变量指向了digits的引用变量,此时的数组的长度就变成了3
        digits = numbers;

        System.out.println(digits.length);//3

        digits[3] = 6;
        System.out.println(digits.length);//java.lang.ArrayIndexOutOfBoundsException

    }
}

digits的长度从4变成3,那是栈内存指向了堆内存数据等于3长读的数据。另外的4个数据就等待垃圾回收。

如果堆内存的数据元素也存放的是引用类型。此时数组元素存放引用,指向另外一快内存,在其中存放有效的数据。

package com.eminem.vo;

class Person{
    public int age;
    public String name;

    public void show(){
        System.out.println(name+"的年龄:"+age);
    }
}
public class TestDemo {
    public static void main(String[] args) {
        //静态定义一个数组
        Person[] persons;
        //分配内存空间
        persons = new Person[2];

        Person p1 = new Person();
        p1.age=10;
        p1.name="zs";

        Person p2 = new Person();
        p2.age=20;
        p2.name="ls";

        for (Person person : persons) {
            System.out.println(person);//null 由于还未给数组引用变量的null对象赋值
        }

        persons[0] = p1;
        persons[1] = p2;

        for (Person person : persons) {
            person.show();
        }
    }
}

分析如下:

也就是栈内存存放了对堆内存的引用,堆内存的数组元素又引用了其他内存。

package com.eminem.vo;

public class TestDemo {
    public static void main(String[] args) {
        //定义一个二维数组,一维是栈内存引用堆内存的数组元素,
        //二维是被栈引用的堆内存的数组元素的其中一个又去引用堆内存的其他数组元素
        int [][] numbers;

        numbers = new int[3][];//静态初始化,长度为3的数组

        for (int i =0;i<numbers.length;i++) {
            System.out.println(numbers[i]);//null
        }

        System.out.println("---------");

        //栈内存引用堆内存的第一个数组元素又引用堆内存的其他数组元素
        numbers[0] = new int[2];

        //栈内存引用堆内存的第一个数组元素又引用堆内存的其他数组元素中的第二个元素1
        numbers[0][0] = 1;
        numbers[0][1] = 2;
        for (int i = 0; i < numbers[0].length; i++) {
            System.out.println(numbers[0][i]);
        }

        System.out.println("---------");

        numbers[2] = new int[3];
        numbers[2][0] = 5;
        numbers[2][1] = 6;
        numbers[2][2] = 7;
//        numbers[2][3] = 8; // 由于第三个数组元素引用堆内存的其他数组元素的长度为3,超过了 java.lang.ArrayIndexOutOfBoundsException

        for (int i = 0; i < numbers[2].length; i++) {
            System.out.println(numbers[2][i]);
        }

        System.out.println("---------");

//        numbers[3] = new int[1];// 由于numbers只定义了长度为3的数组元素 java.lang.ArrayIndexOutOfBoundsException
    }
}

数组工具类:Arrays类

package com.eminem.vo;

import java.util.Arrays;

public class TestDemo {
    public static void main(String[] args) {
        int[] a = {3, 4, 5, 6};
        int[] b = {3, 4, 5, 6};
        //比较a与b是否相等
        System.out.println(Arrays.equals(a, b));
        //查找4在a的位置
        System.out.println(Arrays.binarySearch(a, 4)); //1
        //拷贝a到c,并设c长度为6
        int[] c = Arrays.copyOf(a, 6);
        System.out.println(c.length); //6
        //打印数组c
        System.out.println(Arrays.toString(c)); //[3, 4, 5, 6, 0, 0]

        //将a中的所有值赋值为1
        Arrays.fill(a, 1);
        System.out.println(Arrays.toString(a));//[1, 1, 1, 1]
        //将c中的第三个到第五个赋值为2
        Arrays.fill(c, 2, 5, 2);
        System.out.println(Arrays.toString(c));//[3, 4, 2, 2, 2, 0]
        //快速排序c
        Arrays.sort(c);
        System.out.println(Arrays.toString(c)); //[0, 2, 2, 2, 3, 4]
    }

}

参考资料:

http://www.cnblogs.com/hmiinyu/archive/2012/10/22/2732781.html

时间: 2024-10-14 10:44:41

数组的引用变量和内存分配的相关文章

Java变量以及内存分配

Java变量以及内存分配(非常重要) 堆栈 静态存储区域 一个由C/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈. 2.堆区(heap)— 由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收.注意它与数据结构中的堆是两回事,分配方式倒是类似于链表. 3.全局区(静态区)(static)— 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的

C语言变量声明内存分配

转载: C语言变量声明内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 程序运行时由编译器自动分配,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.程序结束时由编译器自动释放. 2.堆区(heap) — 在内存开辟另一块存储区域.一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 .注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵. 3.全局区(静态区)(static)—编译器编译时即分配内存.全局变量和静态变量

数据结构基础(1)--数组C语言实现--动态内存分配

数据结构基础(1)--数组C语言实现--动态内存分配 基本思想:数组是最常用的数据结构,在内存中连续存储,可以静态初始化(int a[2]={1,2}),可以动态初始化 malloc(). 难点就是数组在删除或者插入元素的时候,要移动元素的坐标不好确定.规律: 1.如果要在数组中第pos个位置插入一个元素(应该从后面开始移动) for( i=cnu;i>=pos;i--) pBase[i]=pBase[i-1]; 2.删除数组第pos位置的元素 for(i=pos+1;i<=cnu;i--)

C/C++ | 变量的内存分配

C/C++ 程序占用的内存分布: 栈区(stack): 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.  堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 . 全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域.程序结束后由系统释放  文字常量区:常量字符串就是放在这里的. 程序结束后由系统释放  程序

变量、参数和内存分配

变量的类型 按作用范围可以把变量分为局部变量和全局变量 参数的类型 实参和形参 变量的内存分配——静态和动态 静态变量的声明关键字:static 动态变量的声明,内存的动态分配可以使用函数malloc(字节数) 栈机制——运行时内存布局(Runtime Memory Layout) 一个程序要运行,就要先将可执行文件装载到计算机内存中.装载是操作系统掌控的,一般而言,操作系统将程序装入内存后,将形成一个随时可以运行的进程空间,改进程空间分四个区域,由上到下为:代码区(code area).全局数

JAVA基础-栈与堆,static、final修饰符、内部类和Java内存分配

Java栈与堆 堆:顺序随意 栈:后进先出(Last-in/First-Out). Java的堆是一个运行时数据区,类的对象从中分配空间.这些对象通过new.newarray.anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放.堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据.但缺点是,由于要在运行时动态分配内存,存取速度较慢. 栈的优势是

Java内存分配、管理小结

 想写这篇总结酝酿了有个来月了,却始终感觉还差点什么东西,一直未敢动笔. 最近两天连夜奋战,重新整理下前面查阅的资料.笔记,还是决定将它写出来. 现在提出几个问题,如果都能熟练回答的大虾,请您飘过.如以往一样,我是小菜,本文自然也是针对小菜阶层的总结. 首先是概念层面的几个问题: Java中运行时内存结构有哪几种? Java中为什么要设计堆栈分离? Java多线程中是如何实现数据共享的? Java反射的基础是什么? 然后是运用层面: 引用类型变量和对象的区别? 什么情况下用局部变量,什么情况下用

java内存分配详细论

P.S. 想写这篇总结酝酿了有个来月了,却始终感觉还差点什么东西,一直未敢动笔. 最近两天连夜奋战,重新整理下前面查阅的资料.笔记,还是决定将它写出来. 现在提出几个问题,如果都能熟练回答的大虾,请您飘过.如以往一样,我是小菜,本文自然也是针对小菜阶层的总结. 首先是概念层面的几个问题: Java中运行时内存结构有哪几种? Java中为什么要设计堆栈分离? Java多线程中是如何实现数据共享的? Java反射的基础是什么? 然后是运用层面: 引用类型变量和对象的区别? 什么情况下用局部变量,什么

数据结构-c语言内的内存分配

常用到的数据存储区: 在C语言中,根据数据在内存中存在的时间(生存期)不同,将内存空间分为三个区: 1.程序区:用于存储程序的代码,即程序的二进制代码: 2.静态存储区:用于存储全局变量和静态变量,这些变量的空间在程序编译时就已经分配好了: 3.动态存储区:用于在程序执行时分配的内存,又分为:堆区(heap)和堆栈区(stack)两种. 堆区:用于动态内存分配,程序运行时由内存分配函数在堆上分配内存.在C语言中,只要使用指针才能动态的分配内存. 堆栈区:在函数执行时,函数内部的局部变量和函数参数