数组
1. 数组的概念
数组是指在内存中,开辟一块连续的,长度固定的空间,用于存储数据类型相同的内容
2. 创建数组
先声明、再分配空间:
数据类型[] 数组名; int [ ] arr ;
数组名 = new 数据类型[长度]; arr = new int [3] ;
声明并分配空间:
数据类型[] 数组名 = new 数据类型[长度]; int arr [ ] = new int [3];
声明并赋值(繁):
数据类型[] 数组名 = new 数据类型[]{value1,value2,value3,…};
声明并赋值(简):
数据类型[] 数组名 = {value1,value2,value3,…}; //显示初始化,注意:不可换行
2.1 数组的特点:
- 类型相同
- 长度固定
- 空间连续
代码示例:
public class Test1 {
public static void main(String[] args) {
// 方式1 先声明 再分配空间
int [] arr1;
arr1 = new int[5]; // 表示这个数组有5个空间在内存中 可以 存放5个int数值
// 方式2 连声明 带分配空间
int [] arr2 = new int[6];
// 方式3 声明 带赋值 繁
// 这种方式 不要在等号右边的中括号中写长度数值
// 语法格式错误
int [] arr3 = new int[] {11,22,33,44,55,66};
// 方式4 声明 带赋值 简
int [] arr4 = {11,44,5,88,99,77};
}
}
3.数组在内存中的存储&各种数据在内存中的位置
基本数据类型:全部存储在栈中
8 种基本数据类型全部都存储在栈内存中,例如:int a = 1; double b = 2.0;
整句代码都在栈内存中。
引用数据类型:栈中存储的变量名,也就是地址,堆中存的是内容,也就是>值,栈中的引用,指向堆中的空间,就是指针。
例如:String str = " abcde"; String str 在栈内存中存储,"abcde"在堆内存中存储,String str在栈内存 对应的地址值指向"abcde"在堆内存中对应的地址值。
4.数组元素的访问
通过下标(索引:index)来访问,下标从0开始
如果访问超出下标的元素,将会报异常 ArrayIndexOutOfBoundsException
5.数组的默认值
-
数组中的元素都有默认值,根据数组类型的不同,默认值也不同
-
整型:0
-
浮点:0.0
-
布尔:false
-
字符:\u0000
-
其他:null
代码示例:
import java.util.Arrays;
public class Test2 {
public static void main(String[] args) {
byte [] arr1 = new byte[3];
String str1 = Arrays.toString(arr1);
System.out.println(str1);// [0, 0, 0]
short [] arr2 = new short [3];
String str2 = Arrays.toString(arr2);
System.out.println(str2);// [0, 0, 0]
int [] arr3 = new int [3];
String str3 = Arrays.toString(arr3);
System.out.println(str3);// [0, 0, 0]
long [] arr4 = new long [3];
String str4 = Arrays.toString(arr4);
System.out.println(str4);// [0, 0, 0]
float [] arr5 = new float[3];
String str5 = Arrays.toString(arr5);
System.out.println(str5);// [0.0, 0.0, 0.0]
double [] arr6 = new double[3];
String str6 = Arrays.toString(arr6);
System.out.println(str6);// [0.0, 0.0, 0.0]
boolean [] arr7 = new boolean [3];
String str7 = Arrays.toString(arr7);
System.out.println(str7);// [false, false, false]
char [] arr8 = new char[3];
String str8 = Arrays.toString(arr8);
System.out.println(str8);// [ , , ]
String [] arr9 = new String [3];
String str9 = Arrays.toString(arr9);
System.out.println(str9); // [null, null, null]
}
}
6.复制数组的三种方式(有扩容的作用)
-
1.使用循环复制数组
-
2.System.arraycopy(原数组,原数组起始,新数组,新数组起始,长度);
-
3.Arrays.copyOf(原数组, 新长度); 返回一个新的数组
代码示例:
import java.util.Arrays;
/**
* 复制数组的方式 三种
* 1.使用循环复制数组
* 2.System.arraycopy(原数组,原数组起始,新数组,新数组起始,长度);
* 3.Arrays.copyOf(原数组, 新长度); 返回一个新的数组
* @author WHD
*
*/
public class Test1 {
public static void main(String[] args) {
// 方式1
int [] arr1 = {12,45,78,89,56,23};
int [] arr2 = new int[6];
for (int i = 0; i < arr2.length; i++) {
arr2[i] = arr1[i];
}
System.out.println(Arrays.toString(arr2));
// 方式2
int [] arr3 = {12,45,78,89,56,23,88,99};
int [] arr4 = new int[arr3.length];
System.arraycopy(arr3, 1, arr4, 0, 3);
System.out.println(Arrays.toString(arr4));
// 方式3
int [] arr5 = Arrays.copyOf(arr4, 12);
System.out.println(Arrays.toString(arr5));
}
}
7.值传递和引用传递
数组引用数据类型 变量中存储的是数组的地址(引用) 指向堆中的空间
面试题:
值传递和引用传递
基本数据类型都是值传递,引用数据类型都是引用传递,String类型是特殊的引用数据类型,作为参数传递值不会改变
值传递不会改变原参数的值,因为传递的是值的拷贝
引用传递会改变原参数的值,因为传递的是地址
代码示例1:
import java.util.Arrays;
public class Test4 {
public static void main(String[] args) {
int arr1[] = {1,2,3,4,5};
int arr2[] = {6,7,8,9,10};
System.out.println(arr1);// [I@70dea4e
System.out.println(arr2);// [I@5c647e05
System.out.println();
// 将 arr2 的地址值 赋值给 arr1 arr1和arr2在栈内存中的地址
// 指向堆内存中的同一个地址。所以最终打印内容相同。
arr1 = arr2;
System.out.println(arr1);// [I@5c647e05
System.out.println(arr2);// [I@5c647e05
System.out.println(Arrays.toString(arr1)); // [6, 7, 8, 9, 10]
System.out.println(Arrays.toString(arr2)); // [6, 7, 8, 9, 10]
}
}
代码示例2:
import java.util.Arrays;
public class Test5 {
public static void main(String[] args) {
int [] arr1 = {1,2,3,4,5};
System.out.println(Arrays.toString(arr1)); // [1, 2, 3, 4,
// 调用m1方法,传数组类型参数,就相当于将arr1的地址值赋值给m1
//方法中数组参数arr,所以两数组地址值相同,指向同一堆内存中的地址,
// m1方法中对数组中的数进行+1,所以数组最终值都+1
m1(arr1);
System.out.println(Arrays.toString(arr1));// [2, 3, 4, 5,
}
public static void m1(int [] arr) {
for (int i = 0; i < arr.length; i++) {
arr[i] += 1;
}
}
}
7.1 String类型是特殊的引用数据类型,作为参数传递值不会改变
代码示例:
// String类型是特殊的引用数据类型,作为参数传递值不会改变
public class Test6 {
public static void main(String[] args) {
int num = 10;
m1(num);
System.out.println(num);// 10
String str1 = "abc";
m2(str1);
System.out.println(str1);// abc
}
public static void m1(int a) {
a += 10;
}
public static void m2(String str2) {
str2 += "ABC";
}
}
8.可变长参数
可变长参数 可以接受同一个类型的不同个数的实际参数
要求:
1.必须在形参列表的末尾
2.形参列表中只能存在一个
代码示例:
/**
* 可变长参数 可以接受同一个类型的不同个数的实际参数
* 要求:
* 1.必须在形参列表的末尾
* 2.形参列表中只能存在一个
* @author WHD
*
*/
public class Test2 {
public static void main(String[] args) {
m1(11,22,33);
m2(1,2,3,4,5,6);
}
public static void m1(int a,int... nums,int b) {// 这里可变长只能存在形参列表的末尾,编译出错
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + "\t");
}
}
public static void m2(int...nums1,int...nums2) {// 这里不允许存在两个可变长参数,编译出错
}
public static void m3(double... nums) {
}
public static void m4(String... strs) {
}
}