美文网首页
java数组及内存分配

java数组及内存分配

作者: 小糖douer | 来源:发表于2019-01-19 18:26 被阅读0次

    概念

    java提供的数组是用来存储固定大小,相同类型的元素的。

    基本使用方法

    public class ArrayTest {
                
           /**
            * 一维数组的使用
            */
           @Test
           public void array1test() {
               // 数组的定义,java在定义数组时并不为数组元素分配内存,因此[]中无需指明数组长度
               int intArray1[];
               int[] intArray2;
                  
               // 如果要为数组分配空间,需要用到new操作符
               intArray1 = new int[5];
                  
               // 数组的初始化 
               // 1.静态初始化,即声明数组的同时进行初始化
               int intArray3[] = {1,2,3,4}; 
               // 2.动态初始化,先声明数组,之后再进行初始化
               int intArray4[] = new int[5];
               intArray4[0] = 1;
               intArray4[1] = 2;
               intArray4[2] = 3;
               intArray4[3] = 4;
               intArray4[4] = 5;
                  
               // 数组的引用,采用数组名加下标的方法,下标从0开始,每个数组都有一个length属性来表明数组的长度
               System.out.println("intArray4[0]: " + intArray4[0]);
               System.out.println("length of intArray4:" + intArray4.length);
                 
               // 数组的遍历
               // 1. for循环
               for(int i=0; i<intArray4.length; i++)
                   System.out.println("intArray4[" + i + "]:" + intArray4[i]);
                   
               // 2. 增强的for循环,也称为foreach循环
               for(int var : intArray4)
                   System.out.println("  " + var);
               }
           
           /**
            * 二维数组的使用
           */
           @Test
           public void array2Test(){
                /**
                 * 二维数组,可以看做是数组的数组,空间是不连续的,所以不要求二维数组每一维大小相同
                */
                  
                // 数组的声明
                int intArray5[][] = {{1,2},{2,3},{1,3}};
                int intArray6[][] = new int[2][3];
                 
                int intArray7[][] = {{1,2},{1,2,3},{1,2,3,4}};
                
                int intArray8[][] = new int[3][];
                intArray8[0] = new int[2];
                intArray8[1] = new int[3];              
            }
    

    数组的内存分配

    一维数组的内存分配情况

    public class ArrayTest {
            /**
             * java数组必须经过初始化才能使用,而数组一旦初始化该数组所占的内存空间,数组长度都是不可变的。
             */
            
            /**
             * 一维数组的内存分配情况
             */
            @Test
            public void array3Test(){
                // 静态初始化,初始化元素的个数决定了数组大小
                int array0[] = {1,2,3,4,5};
                System.out.println("array0地址: " + array0);
                for(int i=0; i<array0.length; i++){
                     System.out.println("array0[" + i + "]: " + array0[i]);
                }
                // 动态初始化,需要给出数组的大小
                int array1[] = new int[6];
                System.out.println("array1地址: " + array1);
                for(int i=0; i<array0.length; i++){
                     System.out.println("array1[" + i + "]: " + array1[i]);
                }
                  
                array0 = array1;
                System.out.println("现在array0的地址是: " + array0);                          
            }      
    }
    

    运行结果:
    array0地址: [I@e285c6
    array0[0]: 1
    array0[1]: 2
    array0[2]: 3
    array0[3]: 4
    array0[4]: 5
    array1地址: [I@1be5d1
    array1[0]: 0
    array1[1]: 0
    array1[2]: 0
    array1[3]: 0
    array1[4]: 0
    现在array0的地址是: [I@1be5d1

    • 从程序中运行中可以看出,采用静态初始化数组array0时,首先在栈内存中分配一个指向堆内存的地址,然后再堆中分配一段连续的内存空间,保存初始化数据,由此可见,采用静态初始化时,不用指定数组大小,程序会根据初始化数组自动识别数组大小。

    • 采用动态初始化时,需要先指定数组大小,程序自动将堆中的数组初始化为默认数值,int类型,自动初始化为0.

      Java内存对象访问定位0.png
    • 当运行程序array0 = array1时,就是将array0指定array1指向堆内存中的地址,此时array0和array1指向了同样的地址,array0之前指向的地址变成了垃圾。


      Java内存对象访问定位1.jpg

    二维数组的内存分配情况

    package jdk.collection;
    
    import org.junit.Test;
    
    public class ArrayTest {
           /**
             * 二维数组的内存分配情况
             */
            @Test
            public void array4Test(){
                // 不指定二维
                int array2[][] = new int[3][];
                System.out.println("array2地址:" + array2);
                for(int i=0; i<array2.length; i++)
                     System.out.println("array2[" + i + "]:" + array2[i]);
                   
                // 指定二维
                int array3[][] = new int[3][2];
                System.out.println("array3地址: " + array3);
                for(int i=0; i<array3.length; i++)
                     System.out.println("array3[" + i + "]:" + array3[i]);
                
                System.out.println("array3[2][1] = " + array3[2][1]);
                   
                array3[1] = array3[0];
                array3[2] = new int[3];
                for(int i=0; i<array3.length; i++)
                     System.out.println("array3[" + i + "]:" + array3[i]);
            }
    

    运行结果:

    array2地址:[[I@e285c6
    array2[0]:null
    array2[1]:null
    array2[2]:null
    array3地址: [[I@1be5d1
    array3[0]:[I@13fd745
    array3[1]:[I@1327b79
    array3[2]:[I@12410ac
    array3[2][1] = 0
    array3[0]:[I@13fd745
    array3[1]:[I@13fd745
    array3[2]:[I@2c41f4

    • 从程序运行结果可以看出,当不指定二维大小时,int array2[][] = new int[3][]创建了一个指向3个地址的地址,并且3个地址指向null;而int array3[][] = new int[3][2]创建了一个指向3个地址的地址,并且这3个地址分别指向了3个初始化为0的内存空间。
    Java内存对象访问定位2.jpg

    java二维数组实际上是指向地址的地址,因而array3[1] = array3[0]; array3[2] = new int[3]表明,array3[1]指向了array3[0]的地址,而array3[2]指向了一个新的含有3个int类型的地址。

    Java内存对象访问定位3.png

    存放对象类型的数组

    首先定义一个Person类

    package jdk.collection;
    
    public class Person {
        private String name;
        private int age;
        
        public Person(){};
        public Person(String name, int age){
            this.name = name;
            this.age = age;
        }
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        
    //  public String toString(){
    //      return "name: " + name + "   age:" + age;
    //  }
    }
    
    

    定义存放Person对象的数组

    package jdk.collection;
    
    import org.junit.Test;
    
    public class ArrayTest {
           @Test
            public void array5Test(){
                
                Person array4[];
    //          System.out.println("array4地址:" + array4); // 编译不过去
                array4 = new Person[3];
                System.out.println("array4地址:" + array4);
                
                //直接进行初始化
                Person array5[] = {new Person("张三",16),new Person("李四",20)};
                System.out.println("array5地址:" + array5);
                for(int i=0; i<array5.length; i++){
                    System.out.println("array5[" + i + "]地址:" + array5[i]);
                    System.out.println("array5[" + i + "].getname:" + array5[i].toString());
                }
                
                // 先声明再初始化
                Person array6[] = new Person[3];
                for(int i=0; i<array6.length; i++){
    //              System.out.println("初始化前array6[" + i + "]地址:" + array6[i]);
    //              System.out.println("初始化前array6[" + i + "]内容:" + array6[i].toString());
                }
                
                Person per0 = new Person("王五",17);
                Person per1 = new Person("周六",18);
                array6[0] = per0;
                array6[1] = per1;
    //          for(int i=0; i<array6.length; i++){
                for(int i=0; i<2; i++){
                    System.out.println("赋值后array6[" + i + "]地址:" + array6[i]);
                    System.out.println("赋值后array6[" + i + "]内容:" + array6[i].toString());
                }
                System.out.println("per0地址:" + per0 + "   per1地址:" + per1);
                
            }
    

    运行结果
    array4地址:[Ljdk.collection.Person;@e285c6
    array5地址:[Ljdk.collection.Person;@1be5d1
    array5[0]地址:jdk.collection.Person@13fd745
    array5[0].getname:jdk.collection.Person@13fd745
    array5[1]地址:jdk.collection.Person@1327b79
    array5[1].getname:jdk.collection.Person@1327b79
    赋值后array6[0]地址:jdk.collection.Person@12410ac
    赋值后array6[0]内容:jdk.collection.Person@12410ac
    赋值后array6[1]地址:jdk.collection.Person@2c41f4
    赋值后array6[1]内容:jdk.collection.Person@2c41f4
    per0地址:jdk.collection.Person@12410ac per1地址:jdk.collection.Person@2c41f4

    可以类比二维数组,存放对象类型的一维数组,就是定义了一个指向数组,该数组指向存放对象的地址。
    Person array4[];仅仅声明了array4是一个指向Person对象的数组,并没有为其分配地址,只有在new之后才为其分配了。

    Java内存对象访问定位4.png

    Person array5[] = {new Person("张三",16),new Person("李四",20)}定义了一个指向2个Person类型数组的引用,而Person array6[] = new Person[3]仅仅定义了一个指向3个person类型数组的引用,数组并没有初始化,因而无法知道数组指向的地址。


    Java内存对象访问定位5 (1).png

    而对array6进行复制之后,其内存分配情况如图所示,与array5相比较,多了2个单独指向person的引用。

    相关文章

      网友评论

          本文标题:java数组及内存分配

          本文链接:https://www.haomeiwen.com/subject/rrrzdqtx.html