在Java编程中,数组是一种非常重要的数据结构,它允许我们存储多个值在一个单一的变量中。本文将深入探讨Java数组的基本概念、创建和使用方法,以及如何处理常见的数组问题。
可以看成是相同元素的一个集合。在内存中是一段连续的空间。
数组有以下三个特点:
T[] 数组名=new T[n];
T: 表示数组中存放元素的类型
T[]: 表示数组的类型
N:表示数组长度
int[] array1=new int[10];//创建一个可以容纳10个int类型元素的数组 double[] array2=new double[5];//创建一个可以容纳5个double类型元素的数组 String[] array3=new double[3];//创建一个可以容纳3个字符串元素的数组
数组的初始化主要分为动态初始化以及静态初始化
int[] array = new int[10];
语法格式:T[] 数组名称={data1,data2,...,datan};
int[] array1=new int[]{0,1,2,3,4,5,6,7,8,9}; double[] array2=new double[]{1.0,2.3,3.4,}; String[] array3=new String[]{"hello","world"};
注意事项
int[] array1; array1=new int[10]; int array2; array2=new int[]{1,2,3,4,5};
类型 | 默认值 |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0 |
float | 0.0f |
double | 0.0 |
char | /u0000 |
boolean | false |
如果数组存储元素类型为引用类型,默认值为null
数组在内存中是一段连续的空间,编号是从0开始的,依次递增,该编号称为数组的下标,数组可以通过下标访问任意位置的元素。
需要注意的是,数组是一段连续的内存空间,因此支持随机访问,即通过下标快速访问数组中任意位置元素,因为下标是从0开始的,介于[0,n)之间不包含n(即左闭右开),n为元素个数不能越界,否则会报出下标越界异常。
遍历,即将数组中所有的元素都访问了一遍,访问是指对数组中的元素进行某种操作,比如打印。
int[] arr=new int[]{1,2,3,4,5}; System.out.println(arr[1]); System.out.println(arr[2]); System.out.println(arr[3]); System.out.println(arr[4]); System.out.println(arr[5]);
上述代码实现了对数组中的元素遍历目的,但也发现了一些问题:
上述的代码中,对数组中每个元素的操作都是相同的,则可以使用循环来进行打印。
int[] arr =new int[]{1,2,3,4,5}; for(int i=0;i<5;i++) { System.out.println(arr[i]); }
改成循环之后,上述的三个缺陷可以将2和3解决,但问题1并不能很好解决。但在Java中可以通过数组对象.length来获取数组长度。
int[] arr=new int[]{1,2,3,4,5}; for(int i=0;i<arr.length;i++) { System.out.println(arr[i]); }
也可以使用for-each遍历数组
int[] array={1,2,3}; for (int x:array) { System.out.println(x); }
我们在写代码的时候也会遇到另外一个东西,即length()。那么他与length的区别是什么呢?
共同点,都可以求得某个数据的长度。
不同点,length是数组的一个属性,他返回数组能够容纳的元素数量。当创建数组时这个值就被确定了并且在整个数组的生命周期都不会改变;length()是String类的一个方法,用于返回字符串中的字符数。对于字符串而言,这个方法返回的是序列中实际字符数量,而不是像数组那样返回可容纳元素的数量。
总的来说,length是数组的属性,表示数组可以存储的元素数量;length()是字符串的方法,表示字符串中的字符数量在使用时,根据不同的数据类型选择适当的方式获取长度信息。
Java的数组是引用数据类型,这就意味着数组本身存储的是数组对象在内存中的地址,而不是数组元素的值,而这种设计不得不提到初始JVM的内存分布。
内存是一段连续的存储空间,主要用来存储程序运行时数据的,因此JVM也对所使用的内存按照功能的不同进行了划分。
基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值;而引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在的空间地址。引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量可以去操操作对象。这类似于C语言中的指针,但是Java中引用要比指针的操作更简单。
null在Java中表示"空引用",也就是一个不指向对象的引用,null的作用类似于C语言中的NULL(空指针),都是表示一个无效的内存位置,因此不能对这个内存进行任何读写操作。一旦尝试读写,就会抛出NullPointerException,需要注意的是由于Java没有指针,null和0号地址没有任何关联。
Java数组这么设计有以下几个原因
小结:Java的数组作为引用数据类型,不仅提供了更大的灵活性和内存管理的便利,而且与Java的整体面向对象的设计理念相契合。
int[] a={1,2,3,4,5};
public static void main(String[] args) { int num=0; func(num); System.out.println("num"+num); } public static void func(int x) { x=10; System.out.println(”x=“+x); } //执行结果 //num=10 //x=0
在func方法中修改形参x的值,不影响实参的num值
public static void main(String[] args) { int[] arr={1,2,3}; func(arr); System.out.println("arr[0]="+arr[0]); } public static void func(int[] a) { a[0]=10; System.out.println("a[0]="+a[0]); } //执行结果 //a[0]=10 //arr[0]=10
在func方法中内部修改数组的内容,方法外部数组内容也发生改变。因为数组是引用类型,按照引用类型传递的,是可以修改其中存放的内容的。
小结:所谓的”引用“本质上只是存放了一个地址。Java将数组设定成引用类型,这样的话后续进行数组传参,其实只是将数组地址传入到函数形参中,这样可以避免对整个数组的拷贝,如果数组很长那么拷贝的开销就会很大。
求斐波那契数列的前n项
public class TestArray { public static int [] fib ( int n ) { if ( n <= 0 ){ return null ; } int [] array = new int [ n ]; array [ 0 ] = array [ 1 ] = 1 ; for ( int i = 2 ; i < n ; ++ i ) { array [ i ] = array [ i - 1 ] + array [ i - 2 ]; } return array ; } public static void main ( String [] args ) { int [] array = fib ( 10 ); for ( int i = 0 ; i < array . length ; i ++ ) { System . out . println ( array [ i ]); } } }