Java学习笔记 第六天
第一章 数组
概念: 数组是一种容器,可以同时存放多个同一数据类型的数据
特点: 1.数组是一种引用数据类型,而非基本数据类型
2.数组当中的所有数据,类型必须统一
3.数组的长度在程序运行期间不可改变
数组的初始化: 在内存当中创建一个数组,并向其中赋予一些默认值
两种常见的初始化: 动态初始化(指定数组长度);静态初始化(指定数组内容)
注意:
数组不同于String,String是不可变类型,相当于常量,其内容不可改变。但是数组是可变类型,他的内容顺序等都是可以通过后面所学的java.util.Arrays类里的一些方法(大多为静态方法)改变的
- 动态初始化数组格式:
数据类型[] 数组名称 = new 数据类型[数组长度];如, int[] arrayA = new int[3];
左侧数据类型:也就是数组当中保存的数据,全部都是统一的什么数据类型
左侧中的中括号:代表我是一个数组,否则和定义变量有点像
左侧数组名称:给数组取一个名字
右侧的new:代表创建数组的动作
右侧数据类型:必须和左边的数据类型保持一致
有侧中括号的长度:也就是数组当中,到底可以保存多少个数据,是一个int类型的数字
- 静态初始化数组格式:
数据类型[] 数组名称 = new 数据类型[]{元素1,元素2,…};如,int[] arrayB = new int[] {3,4,5};
虽然静态初始化没有直接告诉长度,但是根据大括号里面的元素具体内容,也可以自动推算出来长度。
1.1 数组的两种初始化拓展操作
拓展操作 | 动态初始化 | 静态初始化 |
---|---|---|
省略格式 | \ | 数据类型[] 数组名称 = {元素1,元素2,元素3,…};如,int[] arrayA = {1,2,3,4,5}; |
拆分为两个步骤 | 可以拆分为两个步骤。如:int[] arrayA; arrayA = new int[5]; | 静态初始化标准格式也可拆分为两个步骤。 如:int[] arrayB; arrayB= new int[]{1,2,3,4,5} 但如果静态初始化采用省略格式,则无法进行拆分 |
注意:
1.动态初始化只有标准格式,静态初始化具有省略格式。
2.拆分为两个步骤无论对于动态初始化还是静态初始化都只能对标准格式进行拆分。当然了,动态初始化没有省略格式。
1.2 数组的使用
直接打印数组名称会返回数组的内存地址哈希值(一个16进制的特殊数据)
public class Demo01{
public static void main(String[] args){
int[] arrayA = {1,2,3};
System.out.println(arraA); // [I@50cbc42f
}
}
访问数组元素的格式和Python一样:数组名称[索引值]
数组索引值范围和Python一样:0~数组长度-1
1.3 数组初始化时的默认值
使用动态初始化时:
- 如果数组中数据类型是整型,则默认值为0;
- 如果数组中数据类型是浮点型,则默认值为0.0;
- 如果数组中数据类型是字符型,则默认值为\u0000;
- 如果数组中数据类型是布尔类型,则默认值为false;
- 如果数组中数据类型是引用数据类型,则默认值为null;
使用静态初始化时:
静态初始化也有默认值的过程,只不过系统马上将默认值替换为了大括号当中的具体数值
1.4 内存
Java的内存共划分为5个部分:
-
栈:
存放的都是方法当中的局部变量(方法的参数,或者是方法{}内部的变量)。方法的运行一定是在栈当中运行的,也就是进栈 。 -
堆:
凡是new出来的东西,都在堆当中。
堆内存里面的东西都有一个16进制的地址值
堆内存里面的数据,都有默认值。规则:
如果是整数: 默认是0
如果是浮点型: 默认是0.0
如果是字符型: 默认是’\u0000’
如果是布尔类型: 默认是false
如果是引用类型: 默认是null -
方法区:
存储.class信息,包含方法的信息。 -
本地方法栈:
与操作系统有关 -
寄存器:
与cpu有关
1.4.1只有一个数组时的内存变化过程
1.4.2 两个数组的内存变化过程
1.4.3 两个引用指向同一个数组的内存图
1.6 数组的两个异常
索引越界异常(ArrayIndexOutOfBoundsExpection) :原因在于索引编号错了
public class Demo01ArrayIndex {
public static void main(String[] argas) {
int[] array = new int[]{15, 25, 35};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
// 错误写法
// 并不存在3号元素,所以发生异常
// System.out.println(array[3]);
}
}
空指针异常(NullPointerException):原因在于忘了new
所有的引用数据类型变量都可以赋值为一个null值,但是代表其中什么都没有
数组必须进行new初始化以后才可以使用其中的元素,如果只是赋值了一个null,没有进行new创建,那么将会发生NullPointerException异常
public class Demo02ArrayNull {
public static void main(String[] args) {
int[] array = {1,2,3};
array = null; // 这行代码意味着变量array将不再保存数组的内存地址,也就不允许再操作我们的数组了,因此运行时会抛出NullPointerException异常
System.out.println(array[0]);
}
}
内存变化如下所示:
解决空指针异常(NullPointerException)的办法,补上new即可
public class Demo02ArrayNull {
public static void main(String[] args) {
int[] array = null;
array = new int[3];
System.out.println(array[0]);
}
}
1.7 数组长度
获取格式:
数组名称.length
注意:
数组一旦创建,在程序运行期间,长度不可改变
1.8 遍历数组
遍历数组,说的就是对数组当中的每一个元素进行逐一、挨个处理。默认的处理方式就是打印输出。
public class Demo04Array{
public static void main(String[] args){
int[] array = {1,7,2};
// 在idea中直接一句话array.fori即可生成下列for循环的主体结构
for(int i = 0;i < array.length;i++){
System.out.println(array[i]);
}
}
}
1.9 练习—数组的反转
数组元素的反转:
本来的样子:[1,5,2,3]
之后的样子:[3,2,5,1]
要求:不能使用新的数组,就用原来那个唯一的数组
- 用while循环实现
public class Demo07ArrayReverse{
public static void main(String[] args){
int[] arrayA = new int[] {1,2,3};
// 打印本来的样子
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
int min = 0;
int max = arrayA.length - 1;
while(min < max){
int temp = array[min];
array[min] = array[max];
array[max] = temp;
min++;
max--;
}
// 打印反转后的样子
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
- 用for循环实现
public class Demo07ArrayReverse{
public static void main(String[] args){
// 打印本来的样子
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
int[] arrayA = new int[] {1,2,3};
for(int min = 0,max = arrayA.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]);
}
}
}
1.10 数组作为方法的传入参数和返回值
- 数组作为方法的传入参数
数组可以作为方法的参数。当调用方法的时候,向方法的小括号进行传参,传递进去的其实是数组的地址值
public class Demo01ArrayParam {
public static void main(String[] args) {
int[] array = new int[] {10,20,30,40,50};
printArray(array); // 传递进去的就是array当中保存的地址值
System.out.println("============AAA=============");
printArray(array);
System.out.println("============BBB=============");
printArray(array);
System.out.println("============CCC=============");
}
/*
三要素:
返回值类型:只是进行打印而已,不需要进行计算,也没有结果,用void
方法名称:printArray
参数列表:必须给我数组,我才能打印其中元素
*/
public static void printArray(int[] array){
System.out.println("printArray方法收到的参数是:");
System.out.println(array); // 地址值
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
- 数组作为方法的返回值
一个方法可以有0、1、多个参数,但是只能有0或者1个返回值,不能有多个返回值
如果希望一个方法当中产生了多个结果数据进行返回,怎么办?
解决方案:使用一个数组作为返回值类型即可
任何数据类型都能作为方法的参数类型,或者是返回类型
数组作为方法的参数,传递进去的其实是数组的地址值
数组作为方法的返回值,返回的其实也是数组的地址值
public class Demo02ArrayReturn {
public static void main(String[] args) {
int[] result = calculate(10,20,30);
System.out.println("main方法接收到的返回值数组是:");
System.out.println(result); // 地址值
System.out.println("总和:" + result[0]);
System.out.println("平均数:" + result[1]);
}
// 注意这里在定义方法的返回值类型时候写的是int[]
public static int[] calculate(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};
System.out.println("caculate方法内部数组是:");
System.out.println(array); // 地址值
return array;
}
}