美文网首页
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数组及内存分配

    概念 java提供的数组是用来存储固定大小,相同类型的元素的。 基本使用方法 数组的内存分配 一维数组的内存分配情...

  • 数组内存分配图解

    Java中的内存分配图: 数组的内存图解---- 一个数组 数组的内存图解 ----- 2个数组 数组内存...

  • 数组内存分配图解

    Java中的内存分配图: 数组的内存图解---- 一个数组 数组的内存图解 ----- 2个数组 数组内存图解 -...

  • 数组内存分配图解

    Java中的内存分配图: 数组的内存图解---- 一个数组 数组内存图解 ---- 3个数组/*定义第一个数组,定...

  • Java 中数组的内存分配

    Java 中数组的内存分配 1、Java 程序在运行时,需要在内存中分配空间。为了提高运算效率,就对空间进行了不同...

  • java数组

    1.java数组(先声明再分配内存):在栈内存中保留数组名,用来保存指向数组实体的地址的名称,在堆内存中保留所需内...

  • java-nio

    Non-Direct Buffer:内存分配在java堆中 使用数组存储 ByteBuffer.allocate(...

  • java笔记5

    数组的定义 数组的内存分配及特点 数组操作常见问题 数据常见操作 数组中的数组 @Test public void...

  • java数组的内存分配

    关于引用数据类型数组中的元素到底是类对象,还是指针?答: 参考:https://www.cnblogs.com/m...

  • iOS知识复习笔记(19)---数据结构和算法1

    数组和链表的区别 数组静态分配内存,链表动态分配内存 数组内存中连续,链表不连续 数组元素在栈区,链表在堆区 数组...

网友评论

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

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