1. 数组
- 数组是一种引用数据类型,除了那8个基本数据类型,其他的都是引用数据类型。
- 数组当中的数据,类型必须统一
- 数组的长度在程序运行期间不可以改变
- 无论是基本类型还是引用类型都可以作为数组中的数据
1.1 动态初始化数组--->int[] arrayA = new int[300]
- 在创建数组的时候,直接指定数组中元素的个数
public class Demo01Array {
public static void main(String[] args) {
//创建一个数组,里面可以存放300个int数据
//格式:
//数据类型[] 数组名 = new 数据类型[数组长度]
int[] arrayA = new int[300];
//创建一个数组,可以存放5个字符串
String[] arrayC = new String[5];
}
}
1.2 静态初始化数组--->int [] arrayA = new int[] {5, 15, 25}
- 在创建数组的时候,不直接指定数据个数多少,而是直接将具体的数据内容进行指定
静态初始化的数组也是有长度的
public class Demo02Array {
public static void main(String[] args) {
//直接创建一个数组,里面装的全是int,具体为:5,15,25
//格式
//数据类型[] 数组名称 = new 数据类型[] {元素1, 元素2,...}
int [] arrayA = new int[] {5, 15, 25};
//创建一个数组,用来装字符串:"hello","world","java"
String [] arrayB = new String[] {"hello", "world", "java"};
}
}
1.3 省略格式--->int[] arrayA = {10, 20, 30}
使用静态初始化的时候,格式还可以省略一下。
public class Demo03Array {
public static void main(String[] args) {
//省略格式的静态初始化
//数据类型[] 数组名 = {元素1,元素2,...};
int[] arrayA = {10, 20, 30};
//静态初始化的标准格式可以拆分为两步
int[] arrayB;
arrayB = new int[] {11, 21, 31};
//动初始化的标准格式可以拆分为两步
int[] arrayC;
arrayC = new int[5];
//静态初始化的省略格式不可以拆分为两步
//错误写法
//int[] arrayD;
//arrayD = {11, 21, 31};
}
}
2. 访问数组元素
2.1 静态
public class Demo04Array {
public static void main(String[] args) {
int[] array = {10, 20, 30};
//1. 直接打印数组名 得到的是数组对应的内存地址哈希值。
System.out.println(array);//[I@50cbc42f
//[表示数组
//I表示里面存放的是int类型的
//50cbc42f是一个16进制数
//2. 访问数组里元素的索引值从0开始
System.out.println(array[1]);//20
}
}
2.2 动态
/*
动态初始化数组的时候,其中的元素会自动拥有一个默认值
如果是整数类型,默认值为0
如果是浮点类型,默认值为0.0
如果是字符类型,默认值为'u0000'。其中u表示Unicode,这表示一个不可见字符,打印也看不见
如果是Boolean类型,默认为false
如果是引用类型,默认为null
注意事项:
静态数组初始化也有默认值,只不过程序立刻将默认值替换为大括号里面的值
*/
public class Demo05Array {
public static void main(String[] args) {
int[] array = new int[3];
System.out.println(array);
System.out.println(array[0]);//0
System.out.println(array[1]);//0
System.out.println(array[2]);//0
}
}
3. Java的内存
3.1 一个数组的内存图
public class Demo01ArrayOne {
public static void main(String[] args) {
int[] array = new int[3];
System.out.println(array);//[I@50cbc42f
System.out.println(array[0]);//0
System.out.println(array[1]);//0
System.out.println(array[2]);//0
System.out.println("=================");
//改变数组当中元素的内容
array[1] = 10;
array[2] = 20;
System.out.println(array);//[I@50cbc42f
System.out.println(array[0]);//0
System.out.println(array[1]);//10
System.out.println(array[2]);//20
}
}
- 将public static void main(String[] args)放入方法区,准备将main方法作为程序的起点运行
- 在方法区中查看main方法的信息,将信息main(String[] args) 加载到栈内存当中,并且为main方法在内存当中开辟一个内存空间,这个动作叫做进栈
- 在main方法的栈内存空间中创建一个数组int[] array
- 为数组赋值,在堆里为数组开辟内存空间new int[3],这里会有一个地址值0X666。同时划分出3个小格子。注意:new出来的东西都在堆里
- 地址值0x666会赋值给堆里的数组array。也就是说栈里面变量array存储的其实是一个地址值。有了这个地址值就可以找到堆中数组的内容。
改变数组当中元素的内容
3.2 两个数组的内存图
public class Demo02ArrayTwo {
public static void main(String[] args) {
int[] arrayA = new int[3];
System.out.println(arrayA);//[I@50cbc42f
System.out.println(arrayA[0]);//0
System.out.println(arrayA[1]);//0
System.out.println(arrayA[2]);//0
System.out.println("=================");
arrayA[1] = 10;
arrayA[2] = 20;
System.out.println(arrayA);//[I@50cbc42f
System.out.println(arrayA[0]);//0
System.out.println(arrayA[1]);//10
System.out.println(arrayA[2]);//20
System.out.println("=================");
int[] arrayB = new int[3];
System.out.println(arrayB);//[I@75412c2f
System.out.println(arrayB[0]);//0
System.out.println(arrayB[1]);//0
System.out.println(arrayB[2]);//0
System.out.println("=================");
arrayB[1] = 100;
arrayB[2] = 200;
System.out.println(arrayB);//[I@75412c2f
System.out.println(arrayB[0]);//0
System.out.println(arrayB[1]);//100
System.out.println(arrayB[2]);//200
}
}
3.3 两个引用指向同一个数组
public class Demo03ArraySame {
public static void main(String[] args) {
int[] arrayA = new int[3];
System.out.println(arrayA);//[I@50cbc42f
System.out.println(arrayA[0]);//0
System.out.println(arrayA[1]);//0
System.out.println(arrayA[2]);//0
System.out.println("=================");
arrayA[1] = 10;
arrayA[2] = 20;
System.out.println(arrayA);//[I@50cbc42f
System.out.println(arrayA[0]);//0
System.out.println(arrayA[1]);//10
System.out.println(arrayA[2]);//20
System.out.println("=================");
//将arayA数组的地址值赋值给arrayB
int[] arrayB = arrayA;
System.out.println(arrayB);//[I@50cbc42f
System.out.println(arrayB[0]);//0
System.out.println(arrayB[1]);//10
System.out.println(arrayB[2]);//20
System.out.println("=================");
arrayB[1] = 100;
arrayB[2] = 200;
System.out.println(arrayB);//[I@50cbc42f
System.out.println(arrayB[0]);//0
System.out.println(arrayB[1]);//100
System.out.println(arrayB[2]);//200
//再次访问arrayA
//由于arrayA和arrayB数组地址相同,它们引用的是一个数组,修改任意一个会堆另一个造成影响
System.out.println("=================");
System.out.println(arrayA[0]);//0
System.out.println(arrayA[1]);//100
System.out.println(arrayA[2]);//200
}
}
3.4 常见问题
数组索引越界异常ArrayIndexOutOfBoundsException
数组索引编号从0开始到“数组长度-1”为止。如果访问数组编号的时候,索引编号不存在,那么将会发生数组索引越界异常。ArrayIndexOutOfBoundsException。
空指针异常NullPointerException
/*
所有的引用类型都可以赋值为一个null值。但是代表其中什么都没有
数组必须进行初始化才可以使用其中的元素,如果只是赋值了一个null,没有进行new创建,
那么将会发生空指针异常NullPointerException
*/
public class Demo01ArrayNull {
public static void main(String[] args) {
int[] array = null;
//array = new int[3];
System.out.println(array[0]);//NullPointerException
}
}
3.5 数组的长度.length
public class Demo02ArrayLength {
public static void main(String[] args) {
int[] arrayA = new int[3];
int[] arrayB = {1,1,1,1,11,4,3,5,436,54,5,7,7,87,9,9,87};
//1. 获取数组长度,会得到一个int数字代表数组长度
int len = arrayB.length;
System.out.println(len);//17
//2. 数组运行期间长度不可改变
int[] arrayC = new int[3];
System.out.println(arrayC.length);//3
arrayC = new int[5];
System.out.println(arrayC.length);//5
//为什么两次arrayC.length都可以正常打印呢
//因为:arrayC只是数组的名字,new出来的才是数组,这里new int[3]和new int[5]实际上是两个数组,
//实际数据不是存放在名字arrayC栈中的,而是存放在内存堆中的
}
}
对于第二部分的说明如下
遍历数组:对数组当中的每一个元素进行逐一挨个处理。默认方式就是打印输出。
3.6 数组反转
要求:不使用新数组
- 自己
public class Demo03ArrayReverse {
public static void main(String[] args) {
int[] array = {10,20,3,4,5,6,7};
for (int i = 0; i<array.length/2; i++){
int temp = array[i];
array[i] = array[array.length-1-i];
array[array.length-1-i] = temp;
}
for (int i = 0; i<array.length; i++) {
System.out.println(array[i]);
}
}
}
- 视频课
public class Demo03ArrayReverse {
public static void main(String[] args) {
int[] array = {10,20,3,4,5,6,7};
for (int min = 0, max = array.length-1; min < max; min++,max--){
int temp = array[min];
array[min] = array[max];
array[max] = temp;
}
for (int i = 0; i<array.length; i++) {
System.out.println(array[i]);
}
}
}
3.7 数组名作为方法的参数来传递地址
/*
数组可以作为方法的参数
当调用方法的时候,向方法的小括号进行传参,传递进去的其实是数组的地址值
*/
public class Demo01ArrayParam {
public static void main(String[] args) {
int[] array = {10, 20, 30, 40, 50};
System.out.println(array);//地址值
//1. 传入地址
printArray(array);
}
public static void printArray(int[] array) {
System.out.println("printArray接收到的参数是" + array);//2. 接收到的参数也是地址
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);//3. 根据地址找到索引号对应的内容
}
}
}
3.8 数组名作为方法返回地址
/*
任何数据类型都能作为方法的参数类型或者返回值类型
数组作为方法的参数,传递进去的是数组的地址值
数组作为方法的返回值,返回的是数组的地址值
*/
public class Demo02ArrayReturn {
public static void main(String[] args) {
int[] result = cal(10,20,30);
//2. 接收到的是一个地址
System.out.println("main方法接收到的返回的数组名是:"+result);//地址
//3. 根据地址访问数组中的元素
System.out.println("总和"+result[0]);//60
System.out.println("平均数"+result[1]);//20
}
public static int[] cal(int a, int b, int c){
int sum = a+b+c;
int avg = sum/3;
/*int[] array = new int[2];
array[0] = sum;
array[1] = avg;*/
int[] array = {sum, avg};
//1. 返回的是一个地址
System.out.println("cal方法内部数组是:"+array);//地址
return array;
}
}