注释

  • 单行注释:
1
// 单行注释,只注释一行
  • 多行注释:
1
2
3
4
/*
多行注释
多行注释
*/
  • 文档注释:
1
2
3
4
/**
文档注释
文档注释
*/

关键字和字面量

  1. 关键字指的是被Java赋予了特定含义的英文单词
  2. 关键词用户不能随意使用
  3. 字面量这个知识要求学会数据在程序中的书写格式
  4. 字符、字符串在程序中的书写格式要求:字符使用单引号,且单引号内只能有一个字符;字符串使用双引号,对数量没有要求

变量

变量的定义格式:数据类型 变量名称 = 变量值

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class VariableDemo {
public static void main(String[] args) {
String name = "张三";
int age = 25;
float height = 1.86f;
boolean isMarried = false;

System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
System.out.println("身高:" + height);
System.out.println("婚姻状况:" + isMarried);
}
}

注意事项:

  1. 变量要先声明才能使用
  2. 变量是什么类型,就必须装什么类型的数据
  3. 变量只在自己所归属的{}范围内有效(作用域)
  4. 同一个范围内,变量的名称不能重复
  5. 变量定义的时候可以不赋初始值,但在调用/使用时,变量里必须有值
1
2
3
4
5
int a;
int b;
a = 10;
System.out.println(a); // 10
System.out.println(b); // 报错:可能尚未初始化变量b
  1. 一条语句可以定义多个变量,中间使用逗号分隔
1
2
3
4
int a = 10,b = 20,c = 30;
System.out.println(a); // 10
System.out.println(b); // 20
System.out.println(c); // 30

标识符

  • 由数字、字母、下划线(_)和美元符号($)组成
  • 不能以数字开头
  • 不能是关键字
  • 区分大小写

小驼峰命名法(适用于变量、方法):

  • 规范1:标识符是一个单词的时候,所有字母小写
  • 范例1:name
  • 规范2:标识符由多个单词组成的时候,从第二个单词开始,首字母大写
  • 范例2:firstName

大驼峰命名法(适用于类):

  • 规范1:标识符是一个单词的时候,首字母大写
  • 范例1:Student
  • 规范2:标识符由多个单词组成的时候,每个单词的首字母大写
  • 范例2:GoodStudent

数据类型

基本数据类型

主要有

  1. 整数类型:int、long、short、byte
  2. 浮点数:float、double
  3. 字符:char
  4. 布尔:boolean

所有的整数默认为int,所有的小数默认为double

运算符

算数运算符

符号 作用 说明
+ 数据相加
- 数据相减
* 数据相乘
/ 数据相除
% 取模 两个数据做除法的余数

/ 和 % 的区别:两个数据做除法,/ 取结果的商,% 取结果的余数

整数操作只能得到整数,想要得到小数,必须有浮点数参与运算

练习:获取到三位数上个位、十位、百位的数字。如256,个位为6,十位为5,百位为2

答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class OperatorDemo {
public static void main(String[] args) {
int num = 256;
int unitsDigit = num % 10;
int tensDigit = num / 10 % 10;
int hundredsDigit = num / 100;

System.out.println("个位数:" + unitsDigit);
System.out.println("十位数:" + tensDigit);
System.out.println("百位数:" + hundredsDigit);
}
}

当 + 操作中,遇到了字符串,这时 + 就是字符串拼接符,而不是算数运算

自增自减运算符

符号 作用 说明
++ 自增 变量自身的值加1
自减 变量自身的值减1

++ 和 – 既可以放在变量的后边,也可以放在变量的前边

自增自减只能操作变量,不能操作字面量

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Operator2Demo {
public static void main(String[] args) {
// 前置自增和后置自增的区别(自减同理)
int a = 10;
int b = 20;

int c = a++ + 10;
System.out.println("c:" + c); // 20
System.out.println("a:" + a); // 11

int d = ++b + 10;
System.out.println("d:" + d); // 31
System.out.println("b:" + b); // 21

// 自增自减运算符不能操作字面量
System.out.println(10++); // 报错
System.out.println(--10); // 报错

// 特殊写法(实际开发中不建议)
int x = 3;
int y = (x++) + (++x) + (x * 10); // 4 + 4 + 50
System.out.println(x); // 5
System.out.println(y); // 58
}
}

类型转换

隐式转换

  • 把一个取值范围小的数值或者变量,赋值给另一个取值范围大的变量
1
2
3
int a = 10;
double b = a;
System.out.println(b); // 10.0
  • 取值范围小的数据,和取值范围大的数据进行运算,小的会先提升为大的之后,再进行运算
1
2
3
int a = 10;
double b = 12.3;
double c = a + b;
  • byte、short、char三种数据在运算的时候,都会提升为int,然后再进行运算
1
2
3
byte a = 10;
byte b = 20;
byte c = a + b; // 报错,c的数据类型应该是int

强制转换

  • 把一个取值范围大的数值或者变量,赋值给另一个取值范围小的变量
    • 不允许直接复制,需要加入强制转换
  • 格式:目标数据类型 变量名 = (目标数据类型) 被强转的数据
1
2
3
double a = 12.3;
int b = (int)a;
System.out.println(b); // 12

赋值运算符

符号 作用 说明
= 赋值 a=10,将10赋值给变量a
+= 加后赋值 a+=b,将a + b的值赋给a
-= 减后赋值 a-=b,将a - b的值赋给a
*= 乘后赋值 a*=b,将a * b的值赋给a
/= 除后赋值 a/=b,将a / b的值赋给a
%= 取模后赋值 a%=b,将a % b的值赋给a

关系运算符

符号 说明
== a==b,判断a和b的值是否相等,成立为true,不成立为false
!= a!=b,判断a和b的值是否不相等,成立为true,不成立为false
> a>b,判断a是否大于b,成立为true,不成立为false
>= a>=b,判断a是否大于等于b,成立为true,不成立为false
< a<b,判断a是否小于b,成立为true,不成立为false
<= a<=b,判断a是否小于等于b,成立true,不成立为false

逻辑运算符

  • 把多个条件放在一起运算,最终返回布尔类型的值:true、false
符号 介绍 说明
& 逻辑与 并且,遇false则false
| 逻辑或 或者,遇true则true
! 逻辑非 取反
^ 逻辑异或 相同为false,不同为true

短路逻辑运算符

符号 介绍 说明
&& 短路与 作用和&相同,但是有短路效果
|| 短路或 作用和|相同,但是有短路效果
  • 逻辑与&,无论左边true false,右边都要执行
  • 短路与&&,如果左边为true,右边执行,如果左边为false,右边不执行
  • 逻辑或|,无论左边true false,右边都要执行
  • 短路或||,如果左边为false,右边执行,如果左边为true,右边不执行

实际开发中,最常用的是&&||这三个

三元运算符

  • 格式:判断条件 ? 值1 : 值2;
  • 执行流程:
    1. 首先计算判断条件的值
    2. 如果值为true,值1就是运算结果
    3. 如果值为false,值2就是运算结果

运算符优先级

优先级 运算符
1 . () {}
2 !、-、++、–
3 *、/、%
4 +、-
5 >>、<<、>>>
6 <、<=、>、>=、instanceof
7 ==、!=
8 &
9 ^
10 |
11 &&
12 ||
13 ? :
14 =、+=、-=、*=、/=、%=、&=

Scanner键盘录入

使用顺序:

  1. 引入Scanner包
1
import java.util.Scanner
  1. 创建Scanner对象
1
Scanner sc = new Scanner(System.in);
  1. 使用变量接收键入值:
1
int number = sc.nextInt();

完整示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.Scanner;

public class ScannerDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);

int age = sc.nextInt();

String name = sc.next();

double height = sc.nextDouble();
}
}

方法(函数)

方法(函数):一段具有独立功能的代码块,不调用不执行

方法的出现:

  • 可以将挤在一起的臃肿代码,按照功能进行分类管理,提高维护性
  • 提高代码的复用性

方法的基本定义和调用

  • 定义格式:
1
2
3
public static void 方法名() {
// 方法体
}
  • 调用格式:
1
方法名();

示例:

1
2
3
4
5
6
7
8
9
public class MethodDemo01 {
public static void main(String[] args) {
sayHello();
}

public static void sayHello() {
System.out.println("Hello");
}
}

方法的调用流程

  • 方法没有被调用的时候,在方法区中的字节码文件中存放
  • 方法被调用的时候,需要进入到栈内存中运行

方法区:字节码文件加载时进入的内存

栈内存:方法运行时入栈,方法运行结束出栈

带参方法

  • 定义格式:
1
2
3
public static void 方法名(数据类型 参数名1, 数据类型 参数名2) {
// 方法体
}
  • 调用格式:
1
方法名(字面量或变量名);

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MethodDemo02 {
public static void main(String[] args) {
count(10,20); // 结果为:30

int a = 11;
int b = 22;
count(a,b); // 结果为:33
}


public static void count(int num01,int num02) {
System.out.println("结果为:" + (num01 + num02));
}
}

形参:方法定义时声明的参数

实参:方法调用时传入的参数

带返回值方法

  • 定义格式:
1
2
3
4
public static 数据类型 方法名(数据类型 参数名1, 数据类型 参数名2) {	// 也可以为无参方法
// 方法体
return 结果;
}

返回的结果的数据类型一定要与定义方法时的数据类型匹配

  • 调用格式:
1
数据类型 变量名 = 方法名();

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MethodDemo03 {
public static void main(String[] args) {
String str = giveMeFive();
System.out.println(str); // GiveMeFive

int cnt = count(10,20);
System.out.println(cnt); // 30
}

public static String giveMeFive() {
return "GiveMeFive";
}

public static int count(int a,int b) {
return a + b;
}
}

方法的注意事项

  • 方法不调用就不执行

  • 方法与方法之间是平级关系,不能嵌套定义

  • 方法的编写顺序和执行顺序无关

  • 方法的返回值类型为void,表示该方法没有返回值,没有返回值的方法可以省略return语句不写

    • 如果要编写return,后面不能有具体的数据

    • public static void sayHello() {
          System.out.println("Hello");
          return;	// 后面不能有具体的数据
      }
      
      1
      2
      3
      4
      5
      6
      7
      8

      - 当执行到return语句后,就表示该方法已经得到了结果,此时方法就会结束运行

      - ```java
      public static int count(int a.int b) {
      return a + b;
      System.out.println(a + b); // 这条代码不会执行
      }

方法重载

为了减少命名空间,可以使用方法重载,重载条件如下:

  1. 参数数量不同
  2. 参数位置不同
  3. 参数类型不同

但是,返回值不同不能作为重载条件

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class MethodDemo04 {
public static void main(String[] args) {

}

public static void count() {
System.out.println("请放入至少两个数");
}

public static void count(int a) {
System.out.println("请放入至少两个数");
}

public static int count(int a,int b) {
return a + b;
}

// 参数数量不同
public static int count(int a,int b, int c) {
return a + b + c;
}

// 参数类型不同
public static double count(double a,double b) {
return a + b;
}

public static double count(double a,double b,double c) {
return a + b + c;
}

// 参数位置不同
public static double count(double a,int b) {
return a + b;
}

public static double count(int a,double b) {
return a + b;
}

}

流程控制语句

顺序结构

Java程序默认的执行流程,没有特定的语法结构,按照代码的先后顺序,依次执行

大多数的代码都是这样执行的

分支结构

分支结构if语句

if第一种格式:

1
2
3
if (判断条件) {
语句体;
}

执行流程:

  1. 首先计算判断条件的结果
  2. 如果条件的结果为true,则执行语句体
  3. 如果条件的结果为false,则不执行语句体

示例:

1
2
3
4
int age = 17;
if (age < 18) {
System.out.println("未成年");
}

if第二种格式:

1
2
3
4
5
if (判断条件) {
语句体1;
} else {
语句体2;
}

执行流程:

  1. 首先计算判断条件的结果
  2. 如果条件的结果为true,则执行语句体1
  3. 如果条件的结果为false,则执行语句体2

示例:

1
2
3
4
5
6
int age = 19;
if (age < 18) {
System.out.println("未成年");
} else {
System.out.println("成年");
}

if第三种格式:

1
2
3
4
5
6
7
8
if (判断条件1) {
语句体1;
} else if (判断条件2) {
语句体2;
} ...
else {
语句体n+1;
}

执行流程:

  1. 首先计算判断条件1的值
  2. 如果为true就执行语句体1;如果值为false就计算判断条件2的值
  3. 如果为true就执行语句体2;如果值为false就计算判断条件3的值
  4. 如果没有任何判断条件为true,就执行语句体n+1

示例:

1
2
3
4
5
6
7
8
9
10
11
12
int age = 33;
if (age <= 0) {
System.out.println("年龄不存在");
} else if (age < 18) {
System.out.println("未成年");
} else if (age < 35) {
System.out.println("青壮年");
} else if (age < 50) {
System.out.println("中年");
} else {
System.out.println("老年");
}

注意事项:

  1. if语句中,如果大括号控制的是一条语句,大括号可以省略不写
1
2
3
4
5
if (age <= 0)       System.out.println("年龄不存在");
else if (age < 18) System.out.println("未成年");
else if (age < 35) System.out.println("青壮年");
else if (age < 50) System.out.println("中年");
else System.out.println("老年");
  1. if语句的(){}之间不要写分号
  2. if语句的()中需要产生boolean类型的结果(true、false),根据结果决定程序的走向

分支结构switch语句

  • 通过比较值来决定执行哪条分支

switch分支的执行流程

  1. 先计算表达式的值,再拿着这个值去与case后的值进行匹配
  2. 与哪个case后的值匹配为true就执行哪个case块的代码,遇到break就跳出switch分支
  3. 如果全部case后的值与之匹配都是false,则执行default块的代码
1
2
3
4
5
6
7
8
9
10
11
12
switch(表达式) {
case1:
语句体1;
break;
case2;
语句体2;
break;
...
default:
语句体n+1;
break;
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Scanner sc = new Scanner(System.in);
int day = sc.nextInt();
switch (day) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
case 6:
System.out.println("星期六");
break;
case 7:
System.out.println("星期日");
break;
default:
System.out.println("输入数据有误");
break;
}

注意事项:

  1. 表达式类型只能是byte、short、int、char,不支持double、float、long
    • JDK5开始支持枚举
    • JDK7开始支持String
  2. case给出的值不允许重复,且只能是字面量,不能是变量
  3. 正常使用switch的时候,不要忘记写break,否则会发生穿透现象
  4. case后可以用逗号分隔多个字面量,如case 1,2,3: ...

if和switch的选择

  • if适合做条件是区间判断的情况
  • switch适合做:条件是比较值的情况,代码优雅且性能较好

Debug工具

  • Debug:是供程序员使用的程序调试工具,它可以用于查看程序的执行流程,也可以用于追踪程序执行过程来调试程序
  • Debug调试,又被成为断点调试,断点其实是一个标记,告诉Debug从标记的地方开始查看

Snipaste_2025-07-18_20-26-57

循环结构

  • 可以让一段代码重复执行多次

for循环

格式:

1
2
3
for (初始化语句; 条件判断语句; 条件控制语句) {
循环体语句;
}

示例:

1
2
3
for (int i = 0; i < 10; i++) {
System.out.print("第" + i + "次");
}

结果为:第0次第1次第2次第3次第4次第5次第6次第7次第8次第9次


注意事项

  • 循环{}中定义变量,在每一轮循环结束后,都会从内存中释放
  • 循环()中定义的变量,在整个循环结束后,都会从内存中释放
  • 循环语句(){}之间不要写分号

水仙花数

水仙花数的个位、十位、百位的数字立方和等于原数

1
2
3
123	1^3 + 2^3 + 3^3 = 1 + 8 + 27 = 36	36 != 123	不是水仙花数

371 3^3 + 7 ^ 3 + 1^3 = 27 +343 + 1 = 371 371 == 371 是水仙花数

求所有100 ~ 999之间的所有水仙花数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Practice {
public static void main(String[] args) {
for (int i = 100; i < 1000; i++) {
int ge = i % 10;
int shi = i / 10 % 10;
int bai = i / 100;

int cnt = (int) (Math.pow(ge,3) + Math.pow(shi,3) + Math.pow(bai,3));
if (i == cnt) {
System.out.println(i + "是一个水仙花数");
}
}
}
}

循环嵌套

在循环体中,继续出现循环语句

示例:

1
2
3
4
5
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.println(i + "---" + j);
}
}

while循环

格式:

1
2
3
4
while(判断语句) {
循环体语句;
控制语句;
}

示例:

1
2
3
4
5
int a = 0;
while (a < 10) {
System.out.println(a);
a++;
}

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
世界最高山峰珠穆朗玛峰高度是:8848.86米 = 8848860毫米,
假如有一张足够大的纸,它的厚度是0.1毫米,
折多少次就会比珠穆朗玛峰高
*/
double peakHeight = 8848860.0;
double paperThickness = 0.1;
int cnt = 0;
while (paperThickness <= peakHeight) {
paperThickness = paperThickness * 2;
cnt++;
}
System.out.println(cnt); // 27

for和while的选择

  • 功能上是完全一样的,for能解决的while也能解决,反之亦然
  • 使用规范:知道循环次数,使用for;不知道循环次数建议使用while

do…while循环

格式:

1
2
3
4
5
初始化语句;
do {
循环体语句;
条件控制语句;
} while (循环条件);

示例:

1
2
3
4
5
6
int a = 20;
do {
System.out.println(a); // 20
a++;
} while (a < 10);
System.out.println(a); // 21

解释:与while不同(先判断,后执行),do…while即使最开始没有满足循环条件,也会执行一次do括号里的代码(先执行,后判断)

break、continue

  • break:终止循环体内容的执行,也就是说结束当前的整个循环
  • continue:跳过某次循环体内容的执行,继续下一次的执行

break示例:

1
2
3
4
5
6
7
8
int a = 0;
while (true) {
a++;
if (a == 99) { // 当a==99时终止循环
break;
}
}
System.out.println(a); // 99

continue示例:

1
2
3
4
5
6
7
8
int a = 0;
while (a < 50) {
a++;
if (a % 2 == 0) { // 碰到偶数跳过该次循环
continue;
}
System.out.println(a);
}

注意事项:

  • 遇到循环嵌套时,break和continue操作的是内循环
  • break只能在循环和switch中使用,continue只能在循环中进行使用

标号(循环体命名)

当希望break和continue操作外循环时,可以通过给外循环起名(标号),并在break或continue后指定循环体名称即可

示例:

1
2
3
4
5
6
7
8
9
lo:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (j == 2) {
break lo;
}
System.out.println(i + "---" + j);
}
}

lo是loop的缩写,也就是对外层循环起的名称

Random随机数

使用步骤:

  1. 导包:
1
import java.util.Random;
  1. 创建Random对象:
1
Random r = new Random();
  1. 生成随机数:
1
int num1 = r.nextInt(10);	// 范围:0 ~ 9

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.Random;
import java.util.Scanner;

public class Practice {
public static void main(String[] args) {
/*
产生一个1~100的随机数
用户键入一个数字,判断与目标数是否相等
如果不相等,则给出提示(猜大了或猜小了)
*/

Random r = new Random();
int n1 = r.nextInt(100) + 1;

Scanner sc = new Scanner(System.in);


while (true) {
System.out.println("请输入一个1~100的数字:");
int n2 = sc.nextInt();
if (n2 < 1 || n2 > 100) {
System.out.println("注意范围是1 ~ 100哦");
}

if (n2 == n1) {
System.out.println("恭喜您,猜中了");
break;
} else if (n2 > n1) {
System.out.println("猜大了");
} else {
System.out.println("猜小了");
}
}
}
}

数组

数组定义

  • 格式一:数据类型[] 数组名
  • 示例:int[] arr;
  • 格式二:数据类型 数组名[]
  • 示例:int arr[];

在Java中,推荐使用格式一的书写规范

数组静态初始化

  • 初始化:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程
  • 完整格式:数组类型[] 数组名 = new 数据类型[] {元素1, 元素2, 元素3, ...};
  • 示例:int[] arr = new int[] {11, 22, 33};

  • 简化格式:数据类型[] 数组名 = {元素1, 元素2, 元素3, ...};
  • 示例:double[] arr = {11.1, 22.2, 33.3};

推荐使用简化格式,阅读起来更加方便

直接打印数组名,输出的不是数组中的数据,而是数组在内存中的地址(十六进制)。实际上,就也就说明了数组其实是引用数据类型

数组元素访问

  • 格式:数组名[索引];
  • 示例:arr[0];
  • 索引:索引是数组容器中空间的编号,编号从0开始,逐个+1增长

完整代码如下:

1
2
3
4
5
6
7
8
9
public class ArrayDemo01 {
public static void main(String[] args) {
int[] arr = {11,22,33,44,55};
System.out.println(arr[3]); // 44
arr[0] = 55;
System.out.println(arr[0]); // 55
}
}

数组遍历

  • 数组遍历:依次访问数组中的每一个元素
  • 本质:利用for循环访问数组中的元素

示例:

1
2
3
4
5
6
7
8
9
public class ArrayDemo02 {
public static void main(String[] args) {
int[] arr = {11,22,33,44,55,66,77,88,99};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}

进阶用法:

1
2
3
4
5
6
7
8
9
public class ArrayDemo02 {
public static void main(String[] args) {
int[] arr = {11,22,33,44,55,66,77,88,99};

for (int n : arr) {
System.out.println(n);
}
}
}

由于数组是可迭代对象,所以可以直接使用for(数据类型 变量名 : 数组名),也就是增强型for循环或者叫for-each循环

反转数组

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class ArrayReverse {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
reverse(arr);
for (int n : arr) {
System.out.println(n);
}
}

/*
public static int[] reverse(int[] arr) {
int[] tmp = new int[arr.length];
for (int i = arr.length - 1; i >= 0; i--) {
tmp[arr.length - 1 - i] = arr[i];
}
return tmp;
}
*/

public static void reverse(int[] arr) {
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;
}
}
}

  • 第一种反转算法较为简单(从尾到头遍历),但是效率较低
  • 第二种反转算法较为复杂(头尾交换),但是效率较高
  • 最常用的是第二种写法

数组动态初始化

动态初始化:初始化时只指定数组长度,由系统为数组分配初始值

  • 格式:数据类型[] 数组名 = new 数据类型[数组长度];
  • 示例:int[] arr = new int[3];

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ArrayDemo03 {
public static void main(String[] args) {
int[] arr = new int[10]; // 动态初始化
String[] sArr = new String[10];
boolean[] bArr = new boolean[10];
double[] dArr = new double[10];

for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]); // 输出10次结果,都为0
System.out.println(sArr[i]); // 输出10次结果,都为null
System.out.println(bArr[i]); // 输出10次结果,都为false
System.out.println(dArr[i]); // 输出10次结果,都为0.0
}
}
}

动态数组初始化,其实就是将数组中的元素全部以默认值填充,长度由用户指定

数据类型 默认值
整数 0
小数 0.0
字符 ‘\u0000’ 常体现为空白字符
布尔 false
类、接口、数组、字符串 null

动态初始化适用场景:不明确要操作元素的时候,比如随机数生成

二维数组

  • 二维数组是一种容器,该容器用于存储一维数组
  • 完整格式:数据类型[][] 数组名 = new 数据类型[][] {{元素1,元素2,元素3},{元素4,元素5,元素6},{元素7,元素8,元素9,元素10}, ... }` - 简化格式:`数据类型[][] 数组名 = {{元素1,元素2,元素3},{元素4,元素5,元素6},{元素7,元素8,元素9,元素10}, ... }` - 示例:`int[][] arr = {{123},{456},{789}};
  • 访问:arr[1][1]; // 5

完整代码:

1
2
3
4
5
6
public class ArrayDemo04 {
public static void main(String[] args) {
int[][] arr = {{1,2,3},{4,5,6},{7,8,9,10,11}};
System.out.println(arr[1][1]); // 5
}
}

二维数组遍历

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ArrayDemo04 {
public static void main(String[] args) {
int[][] arr = {{1,2,3},{4,5,6},{7,8,9,10,11}};

for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
// 1,2,3,4,5,6,7,8,9,10,11,
System.out.print(arr[i][j] + “,”);
}
}
}
}

常见异常

索引越界异常

  • ArrayIndexOutOfBoundsException:当访问了数字中不存在的索引,就会引发索引越界异常
  • 示例:int[] a = {1,2,3}; a[5] = 15;

空指针异常

  • NullPointerException:当引用数据类型被赋值为null后,地址的指向被切断,如果还继续访问堆内存数据,就会引发空指针异常
  • 示例:
1
2
3
int[] arr = {1,2,3,4,5,6};
rr = null;
System.out.println(arr[0]);

Java内存分配

Java内存分配有以下5种:

  • 栈:每个方法调用生成一个栈帧,存储局部变量、操作数栈、方法出口等信息。例如:main()方法运行时进入栈内存
  • 堆:new出来的东西会在这块内存中开辟空间并产生地址
  • 方法区:存储类元数据(类名、方法名、常量池等)。JDK 8+ 使用元空间(Metaspace)替代,部分功能由堆承担
  • 本地方法栈:用于native方法调用(如Java调用C/C++代码),通过JNI(Java Native Interface)实现
  • 寄存器:CPU内部高速存储单元,用于临时存储指令和数据,是代码执行的核心桥梁

数组内存

数组简化格式:int[] arr = {11,22,33};

但真正运行时,还是按照完整格式运行的:int[] arr = new int[]{11,22,33};