Java中数组的使用和注意事项
Posted 小李德
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中数组的使用和注意事项相关的知识,希望对你有一定的参考价值。
一.初始数组
数组的概念:数组就是一个用来存储相同类型数据的一个容器。
为什么要使用数组?
当我们要存储大量相同类型的时候,通过配合循环来使用就会大量减少代码复杂程度
数组的特点:
(1)数组是一种引用类型.
(2)数组的长度是固定的.
(3)数组中每个元素的类型都是相同的.
二.数组的创建
对于数组的创建,这里和c/c++还是有些不同的,这里创建数组的方法共有三种方法,下面就以数组里面元素为int类型,数组大小为5的举例,如下所示:
(1) 静态初始化
int[] arr = {1,2,3,4,5}
int[] arr = new int[]{1,2,3,4,5};
(2)动态初始化
int[] arr = new int[5];
在这里对于数组的初始化,千万要注意下面这种情况是错误的初始化
int[] arr = new int[5]{1,2,3,4,5};
在这里是不能同时初始化两次,这样会编译不通过,出现错误。
三.使用数组时的注意事项
(1)初始化问题
在创建数组后,如果没有进行赋初值,Java会默认对数组进行初始化,这里对于每种类型的初始值都有不同。
数据类型 | 默认初始值 |
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0 |
double | 0.0 |
char | ‘\\u0000’ |
String | null |
boolean | false |
(2)数组长度的使用
在Java中,可以直接调用Java中自带的方法来求得数组的长度,使用的方法为
数组名.length
String[] f= new String[5];
int len = f.length;
System.out.println(len);//5
(3)有关数组长度的问题
对于数组的长度来说,在进行开辟数组空间的时候就已经确定了,但是在数组长度定义的问题上这里和c/c++有不同的区别,在Java中可以使用变量来进行数组的初始化,例如下面的代码,在Java中是被允许的。
int size = 10;
int[] arr = new int[size];
(4)对于数组的访问
数组的索引相当于门牌号,对每一个元素来说都有对应的位置,如果要进行访问就需要使用指定的索引位置来进行访问
对于数组的访问范围为[0,arr.length),左开右闭的区间范围
但是使用这样的方法来进行访问数组中的每一个元素比较麻烦,下来有一种简单的方法来进行数组的遍历与访问每一个元素
(5)数组的遍历
方法1:
使用普通的for循环来进行来进行访问每一个元素
方法2:
使用增强的for循环来进行遍历数组的每一个元素,相当于对数组的拷贝
两种方法的区别:
在遍历数组的时候,两种方法是没有任何区别的,但是在进行改变数组元素值的时候方法1就可以直接进行数组元素的改变,但是方法2对于基本数据类型的数组是没法来进行改变的。
例题:
给一个数组的每一个元素都乘以2,这里只能用方法1来进行改变,代码如下:
//改变数组中的值
public static void transformArr(int[] arr){
for (int i = 0; i < arr.length; i++) {
arr[i] *=2;
}
}
三.数组的类型
关于类型来分,共有两种类型,一种是基本数据类型一种是引用数据类型
两种类型的概念和区别
基本数据类型:基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值。
引用数据类型:引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址。
在Java中,数组的数据类型是引用数据类型,那么数组是如何进行使用和分配空间的,首先我们需要知道jvm的内存分布
分布图如下所示:
1、每个部分数据区的概念:
(1) 程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址。
(2)虚拟机栈(JVM Stack): 与方法调用相关的一些信息,每个方法在执行时,都会先创建一个栈帧,栈帧中包含有:局部变量表、操作数栈、动态链接、返回地址以及其他的一些信息,保存的都是与方法执行时相关的一些信息。比如:局部变量。当方法运行结束后,栈帧就被销毁了,即栈帧中保存的数据也被销毁了。
(3)本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的。
(4)堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象一般在堆上保存 (例如前面的 new int[]{1, 2,3} ),堆是随着程序开始运行时而创建,随着程序的退出而销毁,堆中的数据只要还有在使用,就不会被销毁。
(5)方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域。
在数组这里我们只需要知道虚拟机栈和堆就可以了
2.数组在JVM当中的使用情况
在这里以使用数组交换两个数来了解数组在虚拟机是如何运行的
(1)代码:
public class Demo{
public static void swap(int[] a){
int tmp = a[0];
a[0] = a[1];
a[1] = tmp;
}
public static void main(String[] args) {
int[] arr = {1,2};
System.out.println("-----交换前------");
System.out.println(Arrays.toString(arr));
swap(arr);
System.out.println("-----交换后------");
System.out.println(Arrays.toString(arr));
}
}
(2)运行结果:
(3)在虚拟机中的运行步骤
交换前执行的结果:
数组开辟的空间是在堆中进行开辟,但是在栈中相当于存储的是数组的首地址,所以在上面例子中,交换的是引用类型中的值,所以能够进行交换原来数组中值。
3.引用类型的注意事项
在使用引用类型数组的时候我们要注意我们改变的是引用类型中的引用还是引用类型中的内容。
在上面的值交换中,我们改变的是引用类型中的内容,那么接下来我们举个例子来说明一下改变引用类型的引用
代码如下:
改变数组中的值
public class Demo{
public static void chaArr(int[] a){
int[] b= new int[3];
a = b;
a[0]=100;
a[1] = 200;
}
public static void main(String[] args) {
int a[] = {10,20};
System.out.println("改变前--------");
System.out.println(Arrays.toString(a));
chaArr(a);
System.out.println("改变后--------");
System.out.println(Arrays.toString(a));
}
}
运行结果:
我们可以发现,在chaArr()方法中我们改变的值在数组中没有发生变化,这是为什么,这是因为,我们在chaArr()中将a的引用地址进行了改变,之后操作的是新创建的数组b中的结果,所以a中的结果没有发生改变,图示如下:
所以在使用数组时要注意是否在中间发生了引用地址的改变。
四.关于引用类型的返回值
在之前学过的返回值都是基本数据类型中的返回值,在学过数组之后,我们知道引用类型也有返回值,接下来我使用返回值来求一个存放斐波那契数列结果的数组,如果所需要的数组大小<=0,则返回null,否则返回一个数组。
代码如下:
public class Demo{
//返回一个斐波纳契数列的数组
public static int[] fibArr(int n){
if(n<=0){
return null;
}
int[] fiArr = new int[n];
fiArr[0] = 1;
if(n==1){
return fiArr;
}
fiArr[1] = 1;
for(int i=2;i<n;i++){
fiArr[i]=fiArr[i-1]+fiArr[i-2];
}
return fiArr;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(fibArr(10)));
}
}
前10项的输出结果如下:
以上是关于Java中数组的使用和注意事项的主要内容,如果未能解决你的问题,请参考以下文章