什么是数组
数组(array)是相同类型变量集合( 这里的集合 不是JDK的Collection )
数组类型的变量是 引用相同类型变量集合的引用变量
java
double[] myList = new double[10];
凡使用new后,内存单元都初始化为 0(值)或 null(引用)
数组元素本身也可以是引用变量。
java
double[][] myList = new double[4][]; //创建一个二维数组
myList[0]=new double[2]; // myList[0]是一个引用变量,指向一个一维数组(2个元素)
myList[3]=new double[3]; // myList[3]是一个引用变量,指向一个一维数组(3个元素)
多维数组只是数组的数组,故数组元素也可能是引用类型变量,**这就让Java中的多维数组的低一维的数组长度不必相同,**这是与C/C++的区别。
声明一维数组引用变量
任何实例化的数组都是Object的子类。数组引用变量声明语法:
datatype[] arrayRefVar ; // 提倡的写法:类型在前,[]在后
例如:double[] myList; //这时myList为null
或者:datatype arrayRefVar[];
例如:
java
double myList[];
double [] a[]; //double[][] a;
数组变量是引用类型的变量 , 声明数组引用变量并不分配数组内存空间 。 必须通过new实例化数组来分配数组内存空间。
创建数组-new
使用new 操作符创建数组。
arrayRefVar = new datatype [arraySize];
例如:myList = new double[10]; // 这时才分配内存
声明和创建在一条语句中: datatype[ ] arrayRefVar = new datatype[ arraySize ] ;
或 datatype arrayRefVar [] = new datatype[ arraySize ] ;
例如:double[] myList = new double[10];或者:double myList[] = new double[10];
数组元素的初始化
新创建的数组对象,其元素根据类型被设置为默认的初始值(实际上都为0)。
数值类型为 0
字符类型为 '\u0000' ,u后面为十六进制, 必须4位写满
布尔类型为 false
引用类型为 null
数组可以在声明后的花括号中提供初始值。
java
double[] myList = {1.9, 2.9, 3, 3.5}//可以将int转化为double类型,这时不用指定维度size
或者
java
double[] myList;
myList = new double[] {1.9, 2, 3.4, 3.5}
//可以将int转化为double类型,声明和创建不在一条语句时,不能直接用{}来初始化
访问数组
数组的大小 在创建这个数组之后不能被改变 。用以下语法访问数组的长度
arrayRefVar.length
数组元素通过索引进行访问。 元素的索引从0开始,范围从0到length-1。
arrayRefVar[index]
示例代码:
java
public class TestArray {
public static void main(String[ ] args) {/** Main method */
final int TOTAL_NUMBERS = 6;
int[] numbers = new int[TOTAL_NUMBERS];
// Read all numbers
for (int i = 0; i < numbers.length; i++) {
String numString = JOptionPane.showInputDialog("Enter a number:");
numbers[i] = Integer.parseInt(numString);
}
// Find the largest
int max = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (max < numbers[i]) max = numbers[i];
}
System.out.println("Max number is " + max);
}
}
数组的复制
直接使用赋值语句不能实现数组复制,结果是两个数组引用变量指向同一个数组对象(浅拷贝赋值)。
复制数组的方法
- 使用循环来复制每个元素
javaint[ ] sourceArray = {2,3,1,5,10}; int[ ] targetArray = new int[sourceArray.length]; for(int i = 0; i < sourceArray.length; i++){ targetArray[i] = sourceArray[i];//=赋值对引用类型是浅拷贝 }
- 使用System.arraycopy方法:两个数组都预先实例化了
java//System.arraycopy方法: sourceArray, targetArray都已经实例化好 //arraycopy(sourceArray,srcPos,targetArray,tarPos,length); System. arraycopy(sourceArray,0,targetArray,0, sourceArray.length);//target要求已存在
src
:源数组,可以是任意类型的数组对象。
srcPos
:源数组中的起始位置,从这个位置开始复制元素。
dest
:目标数组,也是一个任意类型的数组对象,用于接收复制的元素。
destPos
:目标数组中的起始位置,从这个位置开始插入元素。
length
:要复制的元素个数。
- 调用数组的clone方法复制:被复制的数组变量可以没有实例化
javaint[] targetArray= sourceArray.clone();
将数组传递给方法
基本数据类型传递的是实际值的拷贝,修改形参,不影响实参。
数组引用变量传递的是对象的引用,修改形参引用的数组,将改变实参引用的数组, 也可以从方法中返回数组,返回的也是引用。
java
public class TestPassArraySimple{
/** Main method */
public static void main(String[ ] args) {
int x =1;
int[ ] y = new int[10];
y[0] = 20;
m(x, y);
System.out.println("x is " + x);
System.out.println("y[0] is " + y[0]);
}
public static void m(int number, int[ ] numbers) {
number = 1001; //不改变x的值:值参传递
numbers[0] = 5001; //改变y[0]
}
}
String、Integer这样的对象作为参数传递
java
public class CallByReferenceException {
public static void main(String[] args) {
Integer x = Integer.valueOf(10);
testInteger(x);
System.out.println("x = " + x);
String y = "ABC";
testString(y);
System.out.println("y = " + y);
}
public static void testInteger(Integer i) {
i = 20;
System.out.println("i = " + i);
}
public static void testString(String s) {
s = "abc";
System.out.println("s = " + s);
}
}
输出:
i = 20
x = 10
s = abc
y = ABC
引用类型的实参传递给形参后,实参、形参指向同一个对象。
但对于String 类 、基本数据类型的包装类型的实参传递给形参,形参变了不会导致实参变化。这是因为String、Integer的内容是不可更改的,在Integer内部,用private final int****value 来保存整数值,在String内部,用**private final char value[]**来保存字符串内容。
对于String、Integer这样内容不可改变的对象,当对其赋值时实际上创建了一个新的对象。
为什么这么设计?
以Integer为例,因为Integer是int的包装类,它必须要和int的特性一致:int作为方法参数调用时,方法内部对参数的改变不会影响实参。所以Integer必须这么设计
从方法中返回数组
调用方法时,可向方法传递数组引用,也可从方法中返回数组引用
java
//下面的方法返回一个与输入数组顺序相反的数组引用
public static int[] reverse (int[] list){
int[] result = new int [list.length];
for(int i = 0, j = result.lenght - 1; i < list.length; i++,j--){
result [j] = list [i];
}
return result;
}
int[] list1 = {1, 2, 3, 4, 5, 6};
int[] list2 = reverse(list1);
可变长参数列表
可以把类型相同但个数可变的参数传递给方法。
方法中的可变长参数声明如下:
java
typeName ... parameterName
在方法声明中,指定类型后面跟省略号
只能给方法指定 一个 可变长参数,同时 该参数必须是最后一个参数
Java将 可变长参数当数组看待 ,通过 length 属性得到可变参数的个数
java
print(String... args){ //可看作String []args
for(String temp:args)
System.out.println(temp);
System.out.println(args.length);
}
//调用该方法:
print("hello","lisy");
Arrays类
java.util.Arrays类包括各种静态方法,其中实现了数组的排序和查找
排序
java
double[] numbers={6.0, 4.4, 1.9, 2.9};
java.util.Arrays.sort(numbers); //注意直接在原数组排序
二分查找
java
int[ ] list={2, 4, 7, 10, 11, 45, 50};
int index = java.util.Arrays.binarySearch(list, 11);
命令行参数
可以从命令行向java程序传递参数。参数以空格分隔,如果参数本身包含空格,用双引号括起来。格式:
java 类名 参数1 参数2 ...
例如:java TestMain "First number" alpha 53
命令行参数将传递给main方法的args参数。args是一个字符串数组,可以通过数组下标访问每个参数。
public static void main(String[] args)
注意Java的命令行参数不包括类名, args.length**== 3**
可变长参数用...定义。args是一个字符串数组,可以定义为可变长参数。String ... args可以当成String[ ] args数组使用。
public static void main(String ... args) //也可以作为启动函数
注意在定义重载函数时,编译器认为String[] args和String ... args类型相同
多维数组
二维数组:数组的数组
声明二维数组引用变量:dataType[][] refVar;
创建数组并赋值给引用变量:当指定了行、列大小,是矩阵数组 (每行的列数一样)。非矩阵数组则需逐维初始化。
refVar = new dataType[rowSize][colSize]; (这时元素初始值为0或null)
在一条语句中声明和创建数组
dataType[][] refVar = new dataType[rowSize][colSize];
或者:dataType refVar[][ ] = new dataType[rowSize][colSize];
二维数组的每个元素是一个一维数组。int[][] X =new int[3][4];
X指向的是内存里的一个一维数组,数组X的长度是数组X的元素的个数,可由X.length得到,X.length = 3。
元素X[i]是引用,指向另一个一维数组,其长度可由X[i].length得到。
X.length是final的,不可修改。
不规则数组
二维数组每一行的列数可以不同。
创建不规则二维数组时,可以只指定第一维下标。这时第一维的每个元素为null(如下所示),必须为每个元素创建数组。例如:
java
int[][] x = new int[5][]; //第一维的每个元素为null
x[0] = new int[5];//为每个元素创建数组
x[1] = new int[4];
x[2] = new int[3];
x[3] = new int[2];
x[4] = new int[1];
//x.length=5
//x[2].length=3
//x[4].length=1 ,只能取x[4].length的值(它是final的)