🚖 数组
数组就是个容器 数组就是个引用数据类型
什么是容器?
用来东西的工具
数组容器的作用?
用来装数据的,方便对数据进行管理和操作
数组容器的特点?
- 数组容器一旦初始化,长度就固定了,不能再改变
- 数组容器中既可以存储基本数据类型,也可以存储引用数据类型
- 一个数组容器中的所有元素(就是容器中装的东西——数据)的数据类型必须是相同的
数组的定义格式
格式一:
元素的数据类型[] 数组的名字 = new 元素的数据类型[元素的个数(数组的长度)];
int[] arr = new int[5];
格式二:
元素的数据类型[] 数组的名字 = new 元素的数据类型[]{元素1, 元素2, ... ...};
int[] arr = new int[]{12,23,43};
格式三:
元素的数据类型[] 数组的名字 = {元素1, 元素2, ... ...};
int[] arr = {12, 32, 54, 23};//最多四个元素
使用数组容器
创建数组容器?
int[] arr = new int[3];
如何向容器中存储数据?(装东西)
存数据格式:数组名[索引] = 数据;
int arr[0] = 12;
int arr[1] = 2;
int arr[2] = 5;
索引:就是编号,从0开始编号,依次往后,最大的编号是容器的长度-1
如何从容器中取数据?(取东西)
取数据格式:数组名[索引]
int a = arr[0];
int b = arr[1];
int c = arr[2];
数组遍历
就是指将容器中的数据挨个获取出来,打印出来,用循环
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
数组名.length :获取数组容器的长度的
🚓 数组的内存图
Java的内存分配?
堆
栈
*方法区
本地方法栈
寄存器
一个数组的内存图
int[] arr = new int[3];
arr[0] = 12;
arr[2] = 14;
System.out.println(arr[0]);//12
System.out.println(arr[1]);//0
System.out.println(arr[2]);//14
System.out.println(arr);//[I@7852e922
详情参考画图
二个数组的内存图
int[] arr1 = new int[]{23,12,5};
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(arr1[2]);
System.out.println(arr1);
arr1[0] = 13;
System.out.println(arr1[0]);
int[] arr2 = {14,18,15};
System.out.println(arr2[0]);
System.out.println(arr2[1]);
System.out.println(arr2[2]);
System.out.println(arr2);
arr2[1] = 12;
System.out.println(arr2[1]);
一个变量两个数组容器的内存图
int[] arr = new int[3];
System.out.println(arr[0]);
arr[0] = 3;
System.out.println(arr[0]);
System.out.println(arr);
arr = new int[5];
System.out.println(arr[0]);
arr[0] = 5;
System.out.println(arr[0]);
System.out.println(arr);
两个变量指向一个数组容器的内存图
int[] arr1 = new int[3];
System.out.println(arr1[0]);
arr1[0] = 12;
System.out.println(arr1[0]);
System.out.println(arr1);
int[] arr2 = arr1;
System.out.println(arr2[0]);
arr2[0] = 13;
System.out.println(arr2[0]);
System.out.println(arr2);
System.out.println(arr1[0]);
我们在使用数组的时候经常遇到的两个错误?
ArrayIndexOutOfBoundsException(数组索引越界异常)
int[] arr = new int[3];
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);//这一行会引发数组索引越界异常,因为数组中根本没有3索引
NullPointerException(空指针异常) ```java int[] arr = {12,14,13}; System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]);
arr = null; System.out.println(arr[0]);//这一行会引发空指针异常,因为arr的值为null了
注意:null是空常量,只能赋值给引用数据类型的变量
```java
int[] arr = null;
String s = null;
🚔 数组的常见操作
遍历
int[] arr = {1,2,3,4,5};
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
获取最值
方式一
int[] arr = {3,5,2,1,4};
int max = arr[0];//记录的是元素
for(int i = 1; i < arr.length; i++) {
if(max < arr[i]) {
max = arr[i];
}
}
System.out.println(max);
方式二
int[] arr = {3,5,2,1,4};
int max = 0;//记录的是索引
for(int i = 1; i < arr.length; i++) {
if(arr[max] < arr[i]) {
max = i;
}
}
System.out.println(arr[max]);
基本查找
重点
Scanner sc = new Scanner(System.in);
System.out.println("请您输入一个数字:");
int num = sc.nextInt();
int[] arr = {12, 4, 13, 10, 1};
boolean b = false;//false代表没找到,true代表找到了
int index = -1;
for(int i = 0; i < arr.length; i++) {
if(arr[i] == num) {
b = true;
index = i;
break;
}
}
if(b) {
System.out.println("找到了");
} else {
System.out.println("没找到");
}
System.out.println(index); //找到了就输出
数组的反转
反转前:{1,2,3,4,5}
反转后:{5,4,3,2,1}
方式一:
int[] arr = {1,2,3,4,5};
//反转前:
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
for(int i = 0; i < arr.length/2; i++) { //反转操作
int temp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = temp;
}
//反转后:
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
方式二:
for(int i = 0, j = arr.length - 1; i < arr.length / 2; i++, j--) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
排序
排序前:{4,1,5,3,2}
排序后:{1,2,3,4,5}
选择排序
先得最小
int[] arr = {4,1,5,3,2,9};
//排序前:
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
for(int i = 0; i < arr.length - 1; i++) {
for(int j = i + 1; j < arr.length; j++) {
if(arr[i] > arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
//排序后:
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
冒泡排序
先得最大
int[] arr = {4, 1, 5, 3, 2};
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
for(int i = 0; i < arr.length - 1; i++) {
for(int j = 0; j < arr.length-1-i; j++) {
if(arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
🚒 二维数组
元素为一维数组的数组就称为二维数组
二维数组的定义格式
格式一:
元素的数据类型[][] 数组的名字 = new 元素的数据类型[二维数组的长度(一维数组的个数)][一维数组的长度];
int[][] arr = new int[3][2];
这个二维数组中,有几个一维数组呢?
3个
每一个一维数组中有几个元素呢?
2个
格式二:
元素的数据类型[][] 数组的名字 = new 元素的数据类型[二维数组的长度][];
int[][] arr = new int[3][];
这个二维数组中,有几个一维数组呢?
3个
每一个一维数组中有几个元素呢?
不确定,而且每一个一维数组中的元素的个数是可以不一样的
格式三:
元素的数据类型[][] 数组的名字 = {{元素1,元素2,...}, {元素1,元素2,...}, ...};
int[][] arr = {{1,2,3}, {4,5}, {5,6,7,8}};
这个二维数组中,有几个一维数组呢?
3个
每一个一维数组中有几个元素呢?
第一个一维数组中有3个元素
第二个一维数组中有2个元素
第三个一维数组中有4个元素
区别:每一个一维数组中的元素的个数是可以不一样的
二维数组的使用
int[][] arr = new int[3][];
System.out.println(arr);//[[I@7852e922
System.out.println(arr[0]);//null
System.out.println(arr[1]);//null
System.out.println(arr[2]);//null 空指针异常
int[] arr_1 = {1,2,3};
arr[0] = arr_1;
int[] arr_2 = {4,5};
arr[1] = arr_2;
int[] arr_3 = {6,7,8,9};
arr[2] = arr_3;
System.out.println(arr[0]);//[I@4e25154f
System.out.println(arr[1]);//[I@70dea4e
System.out.println(arr[2]);//[I@5c647e05
System.out.println(arr[0][0]);//1
System.out.println(arr[0][1]);//2
System.out.println(arr[0][2]);//3
System.out.println(arr[1][0]);//4
System.out.println(arr[1][1]);//5
System.out.println(arr[2][0]);//6
System.out.println(arr[2][1]);//7
System.out.println(arr[2][2]);//8
System.out.println(arr[2][3]);//9
二维数组的遍历
int[][] arr = {{1,2,3}, {4,5}, {5,6,7,8}};
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
debug一般只执行代码块内的内容(按钮:一个跳到下一行,一个跳到下个断点)
🚁 方法(函数)
具有(特定功能)的一段独立的小程序(代码块)
方法的作用
- 提高了代码复用性
- 提高了代码维护性
方法的定义格式
修饰符 返回值类型 方法的名字(数据类型 变量名, 数据类型 变量名, ...) {
执行语句;(该方法的功能的代码实现)
return 返回值;
}
如何写一个方法?
记住两个明确:
a.明确参数列表
b.明确返回值类型
修饰符:对于现阶段来说,是固定的,public static
例子:
需求:定义一个方法,该方法的功能是获取两个整数之和的
public static int getSum(int i, int j) {
int sum = i + j;
return sum;
}
如何使用方法
方法只有被调用才会执行
怎么调用
- 单独调用:方法名(参数);
注意:如果方法的返回值类型为void的时候,只能使用单独调用
如果方法有具体返回值的时候,使用单独调用没有任何意义
- 输出调用:System.out.println(方法名(参数));
注意:如果方法的返回值类型为void的时候,不能使用输出调用
- 赋值调用:数据类型 变量名 = 方法名(参数);
注意:如果方法的返回值类型为void的时候,不能使用赋值调用
//单独调用
getSum(1,2);
//输出调用
System.out.printIn(getSum(1,2));
//赋值调用
int a = getSum(1,2);
System.out.printIn(a);
方法的执行流程
常见的方法的返回值类型
//定义返回值类型为void的方法 不算数据类型,默认没有返回值
public static void kkk() {
return;
}
//定义返回值类型为数组类型的方法
public static int[] jjj() {
int[] arr = {1,2,3};
return arr;
}
//定义返回值类型为String(字符串)类型的方法
public static String iii() {
return "约吗";
}
//定义返回值类型为char类型的方法
public static char hhh() {
return 'a';
}
//定义返回值类型为boolean类型的方法
public static boolean ggg() {
return false;//true
}
//定义返回值类型为float类型的方法
public static float eee() {
return 12.5F;
}
//定义返回值类型为double类型的方法
public static double fff() {
return 12.5;
}
//定义返回值类型为byte类型的方法
public static byte aaa() {
return 12;
}
//定义返回值类型为short类型的方法
public static short bbb() {
return 12;
}
//定义返回值类型为int类型的方法
public static int ccc() {
return 12;
}
//定义返回值类型为long类型的方法
public static long ddd() {
return 12L;
}
使用方法的时候需要注意哪些问题
方法与方法是平级关系,所以不能嵌套定义
public static int aaa() {
public static int bbb() {
return 1;
}
return 1;
}//错误
方法的返回值类型和返回值要匹配 ```java public static int aaa() { return 1; }
public static double aaa() { return 1; }
public static int bbb() { return ‘a’; }
public static int ccc() { return (int)1.2; }
3. 当方法没有具体的返回值的时候,返回值类型就为void
```java
public static void aaa() {
return ;
}
void:没有什么特殊的含义,而且只能写在返回值类型的位置上,代表该方法没有返回值
注意:当方法的返回值类型为void的时候,return关键字是可以省略不写的
public static void aaa() {
//return;
}
return关键字有什么用
- 可以返回具体的数据,哪里调用返哪里
- 作为方法的结束标记 ```java public static void aaa() { return; System.out.println(“约吗”);//编译报错,因为这行代码永远执行不到 }
public static int aaa() {
if(2 > 1) {
return 1;
}
}//编译报错,因为如果没有进if,就执行不到return,就没有结束标记,也不会返回一个数据了
注意void:看需求确认要不要返回值
```java
//计算两个数的和
public static void getSum(int i,int j) {
int sum = i + j;
return sum; //编译报错,void不返回值
}
//打印两个数的和
public static void printSum(int i,int j) {
int sum = i + j;
System.out.printIn(sum);//打印不需要返回值
return;
}
💽 方法的内存图
一个方法内存图
方法调用完出栈
方法调用其他方法
方法传值给另一个方法
基本数据类型值传递和引用数据类型值传递的问题
案例一:
public class Demo08 {
public static void main(String[] args) {
int i = 1;
int j = 2;
System.out.println(i + "..." + j);//1...2
aaa(i, j);
System.out.println(i + "..." + j);//1...2
i = i + 1;
j = j + 1;
System.out.println(i + "..." + j);//2...3
}
public static void aaa(int i, int j) {
System.out.println(i + "..." + j);//1...2
i = i + 1;
j = j + 1;
System.out.println(i + "..." + j);//2...3
}
}
案例二:
public class Demo09 {
public static void main(String[] args) {
int[] arr = {12,13,14};
System.out.println(arr[0]);//12
System.out.println(arr[1]);//13
System.out.println(arr[2]);//14
aaa(arr); //将数组arr栈地址给aaa方法
System.out.println(arr[0]);//1
System.out.println(arr[1]);//2
System.out.println(arr[2]);//3
}
public static void aaa(int[] arr) {
System.out.println(arr[0]);//12
System.out.println(arr[1]);//13
System.out.println(arr[2]);//14
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
System.out.println(arr[0]);//1
System.out.println(arr[1]);//2
System.out.println(arr[2]);//3
}
}
- 形式参数:形参,在定义方法的时候,小括号里的变量就是形式参数
- 实际参数:实参,在调用方法的时候,传递里面的数据就是实际参数 ```java aaa(arr); //实参 public static void aaa(int[] arr) { //形参
}
<a name="SFPPQ"></a>
## 函数和方法的区别
同样是代码段,但是方法平常往往是和类有关的,即方法放在类里面,而函数则不一定,C中只有函数没有方法,java中有函数也有方法。
<a name="Y1ipr"></a>
# 🚈 方法的重载(Overload)
> 是指在同一个类中,出现两个方法的名字相同,**参数列表不同(参数的个数不同,数据类型不同,对应的顺序位置不同)的两个方法**,就称为方法的重载
- 方法的重载和返回值类型无关
- 根据传的实参不同,调用的方法也不同
例子:
```java
public class Demo01 {
public void aaa() {
}
public void aaa(int i) {
}
public void aaa(int i, int j) {
}
public void aaa(double a, double b) {
}
public void aaa(int i, double a) {
}
public void aaa(double a, int i) {
}
/*public void aaa(double x, int y) {
}*/
/*public int aaa(double a, int i) {
return 1;
}*/
/*
public void aaa() {
}
*/
}