java数组名本质_深入分析Java数组

Posted on 八月 26, 2016

深入分析Java数组

数组的基本介绍:

数组对于每一门编辑应语言来说都是重要的数据结构之一;

数组基本用法:

声明数组变量

首先必须声明数组变量,才能在程序中使用数组。

下面是声明数组变量的语法:

type[] values; // 首选的方法 或type values[]; // 效果相同,但不是首选方法

创建数组

Java语言使用new操作符来创建数组,语法如下:

values = new type [size];

上面的语法语句做了两件事:

一、使用type [size]创建了一个数组。

二、把新创建的数组的引用赋值给变量values。

数组变量的声明,和创建数组可以用一条语句完成,如下所示:

type[] values = new type[10];

另外,你还可以使用如下的方式创建数组。

type[] values = {value0, value1, ..., value10};

数组的元素是通过索引访问的。数组索引从0开始,所以索引值从0到values.length-1。

实例:

下面的语句首先声明了一个数组变量myList,接着创建了一个包含10个double类型元素的数组,并且把它的引用赋值给myList变量。

double[] myList = new double[10];

下面的图片描绘了数组myList,这里myList数组里有10个double元素,它的下标从0到9。

b8062df8a51691df6bbe8505517187c0.png

处理数组

数组的元素类型和数组的大小都是确定的,所以当处理数组元素时候,我们通常使用基本循环或者foreach循环。

常见的数据错误:

使用数组常见错误一:编译出错,没有声明数组初始化大小;

int []array=new int[];

使用数组常见错误二。数组越界。

int []array=new int[1];

array[2]=1;

b4c086d87aa3643176be363b1ba217b1.png

使用数组常见错误三。语法错误。

2210f5db725c485ec9d70b8a08ab5a3f.png

二、数组的深入分析:

数组的内存分配:

java中的数组是用来存储同一种数据类型的数据结构,一旦初始化完成,即所占的空间就已固定下来,初始化的过程就是分配对应内存空间的过程。即使某个元素被清空,但其所在空间仍然保留,因此数组长度将不能被改变。 要向改变数组的空间必须扩容数组操作如下:

//从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。

Arrays.copyOf(T[] original, int newLength);

或者是System.arraycopy(elementData, index, elementData, index + 1, size - index);

当仅定义一个数组变量(int[] numbers)时,该变量还未指向任何有效的内存,因此不能指定数组的长度,只有对数组进行初始化(为数组元素分配内存空间)后才可以使用。

数组初始化分为静态初始化(在定义时就指定数组元素的值,此时不能指定数组长度)和动态初始化(只指定数组长度,由系统分配初始值)。

//静态初始化

int[] numbers = new int[] { 3, 5, 12, 8, 7 };

String[] names = { "Miracle", "Miracle He" };//使用静态初始化的简化形式

//动态初始化

int[] numbers = new int[5];

String[] names = new String[2];

当初始化完毕后,就可以按索引位置(0~array.length-1)来访问数组元素了。

当使用动态初始化时,如在对应的索引位未指定值的话,系统将指定相应数据类型对应的默认值(整数为0,浮点数为0.0,字符为’\u0000’,布尔类型为false,引用类型(包括String)为null)。

public class TestArray {

public static void main(String[] args) {

String[] names = new String[3];

names[0] = "Miracle";

names[1] = "Miracle He";

/*

for(int i = 0; i 

System.out.print(names[i] + " ");

}

*/

//还可以使用foreach来遍历

for(String name : names) {

System.out.print(name + " ");

}

}

}

结果如下:

Miracle Miracle He null

Miracle Miracle He null

数组在内存中如何储存

如图:

b8d4f4fbdcf834347346f1429e1a334a.png

数组引用变量是存放在栈内存(stack)中,数组元素本质是一个对象,是存放在堆内存(heap)中。通过栈内存中的指针指向对应元素的在堆内存中的位置来实现访问。

基本数据类型的数组在内存分配情况:

public class TestPrimitiveArray {

public static void main(String[] args) {

//1.定义数组

int[] numbers;

//2.分配内存空间

numbers = new int[4];

//3.为数组元素指定值

for(int i = 1;i <= numbers.length;i++) {

numbers[i] = i ;

}

}

}

内存分布如图:

b167b069f979abb1aa6d5eb65bd4dd18.png

从图中可看出数组元素直接存放在堆内存中,当操作数组元素时,实际上是操作基本类型的变量。

2、存放引用类型数组在内存中如何储存

先来再看一段存储引用类型数组的实例:

class Person {

public int age;

public String name;

public void display() {

System.out.println(name + "的年龄是: " + age);

}

}

public class TestReferenceArray {

public static void main(String[] args) {

//1.定义数组

Person[] persons;

//2.分配内存空间

persons = new Person[2];

//3.为数组元素指定值

Person p1 = new Person();

p1.age = 28;

p1.name = "Miracle";

Person p2 = new Person();

p2.age = 30;

p2.name = "Miracle He";

persons[0] = p1;

persons[1] = p2;

//输出元素的值

for(Person p : persons) {

p.display();

}

}

}

元素为引用类型的数组,在内存中的存储与基本类型完全不一样。

此时数组元素存放引用,指向另一块内存,在其中存放有效的数据。如图:

ffcd273ecb0f93d76fcd17f553ed96f1.png

在数组参数传递的时候,数组是作为引用参数,传递的是数组的引用指针,将数组引用传递给另一数组引用,但仍然不能改变数组长度(仅仅只是调整数组引用指针的指向)。

二维数组及用法

用法: 定义方式和一维数组类似,如下:

type arrayName[ ][ ];

type [ ][ ]arrayName;

1、初始化:

静态初始化:

int intArray[ ][ ]={{1,2},{2,3},{3,4,5}};

2、动态初始化:

int a[ ][ ] = new int[2][3];

a[0] = new int[3];

a[1] = new int[3];

a[0][1] = new int[4];

a[0][2] = new int[4];

a[0][3] = new int[4];

对二维引用类型的数组,必须首先为最高维分配引用空间,然后再顺次为低维分配空间。而且,必须为每个数组元素单独分配空间。

获取二维数组:

int a[][] = { { 1, 5, 2, 8 }, { 5, 9, 10, -3 }, { 2, 7, -5, -18 } };// 静态初始化一个二维数组

例子:

int a[][] = { { 1, 5, 2, 8 }, { 5, 9, 10, -3 }, { 2, 7, -5, -18 } };

for (int i = 0; i 

for (int j = 0; j <4; j++) {

System.out.println(a[i] + "_" + a[i][j]);

}

}

输出结果:

[I@901a4f3_1

[I@901a4f3_5

[I@901a4f3_2

[I@901a4f3_8

[I@48b02c5_5

[I@48b02c5_9

[I@48b02c5_10

[I@48b02c5_-3

[I@42049d11_2

[I@42049d11_7

[I@42049d11_-5

[I@42049d11_-18

多维数组内存分配:

以二维数组为例:

public static void main(String[] args) {

// 1.定义二维数组

int[][] numbers;

// 2.分配内存空间

numbers = new int[2][];

// 可以把numbers看作一维数组来处理

for (int i = 0; i 

System.out.print(numbers[i] + ",");// null,null,null

}

System.out.println("");

// 3.为数组元素指定值

numbers[0] = new int[2];

numbers[0][1] = 1;

numbers[1] = new int[2];

numbers[1][0] = 11;

numbers[1][1] = 15;

for (int i = 0; i 

for (int j = 0; j 

System.out.print(numbers[i][j] + ",");

}

System.out.println("");

}

}

结果如下:

null,null,

0,1,

11,15,

以一个图展示这个数组在内存中的存储:

fa0bd7034e6637f396af2781f683fd23.png

Array类的用法:

java.util.Arrays类能方便地操作数组,它提供的所有方法都是静态的。静态方法是属于类的,不是属于类的对象。所以可以直接使用类名加方法名进行调用。Arrays作为一个工具类,能很好的操作数组。下面介绍主要使用的几个函数。

1.fill方法:

fill方法主要用来填充数组,这里我们举最简单的int类型吧(其它类型的一样)

看Arrays的fill源码:

384e766e9a8e40567ffc9655921c3a73.png

示例代码:

public static void main(String[] args) {

int a[] = new int[5];

// fill填充数组

Arrays.fill(a, 1);

for (int i = 0; i 

// 输出5个1

System.out.println(a[i]);

}

结果:1 1 1 1 1 1;

填充部分数组源码:

b24c1b699d7ef5097fe5254b0e1efe4c.png

示例:

public static void main(String[] args) {

int a[] = new int[5];

// fill填充数组

Arrays.fill(a, 1, 2, 1);

for (int i = 0; i 

// a[1]=1,其余默认为0

System.out.println(a[i]);

}

结果:0 1 0 0 0;

2.sort方法:

从方法名看都知道是给数组排序,依然用int类型来说,其它类型一样的。

3. equals方法:

用于比较两个数组中的元素值是否相等,还是看int类型的数组。看Arrays源码

0a365a2f4033653a0ab8c3e295096a3e.png

4.binarySearch方法

通过binarySearch方法能对排序好的数组进行二分查找法操作。看源码如下

8551d4e1033508fd103b30a55fddc93f.png

5.copyof方法

复制数组,Arrays的copyOf()方法传回的数组是新的数组对象,所以您改变传回数组中的元素值,也不会影响原来的数组

6……. 方法;

注:在浏览的过程中如果遇到代码样式问题,建议使用Chrome浏览器查看。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值