Java核心语法完整指南
前言:写给Java初学者的话
欢迎学习Java编程!如果你是第一次接触编程,不用担心,我会用最简单的方式带你入门。编程就像学习一门新语言,需要从基础开始,循序渐进。若你是已经有基础的人可以看看我在基础中踩过的坑
学习建议:
- 完全不是背出来的,理解概念很重要
- 每个例子最好自己敲一遍,实操真的非常重要
- 编程是实践技能,多写代码才能掌握
第一章:Java初体验 - 你的第一个程序
1.1 工具选择
个人推荐直接使用idea即可地址直接下载即可www.jetbrains.com/zh-cn/idea/…
1.2 什么是Java程序?
Java程序和其他语言一样就像一本说明书,告诉计算机要做什么。我们写的代码就是这份说明书。
1.3 第一个Java程序:Hello World
idea自带了java的全套工具,但是也是会检测你的Java环境的,关于java安装部分可以参考上一篇安装教程,这里不做赘述
点击新建项目,然后输入项目名称,然后最好是勾选添加示例代码
然后就会自动创建
我们先只看这个部分,去掉for的部分
/**
* @author Anfioo 2026/04/04 22:47
*/
//TIP 要<b>运行</b>代码,请按 <shortcut actionId="Run"/> 或
// 点击装订区域中的 <icon src="AllIcons.Actions.Execute"/> 图标。
public class Main {
public static void main(String[] args) {
//TIP 当文本光标位于高亮显示的文本处时按 <shortcut actionId="ShowIntentionActions"/>
// 查看 IntelliJ IDEA 建议如何修正。
System.out.printf("Hello and welcome!");
}
}
代码解释:
public class HelloWorld:创建一个公共类,类名是HelloWorldmain方法:每个Java程序都必须有这个"大门",程序从这里开始System.out.printf:在屏幕上打印文字- //和/**为注释
- 其实当前无需理解为什么,只要知道这个可以打印一个文字即可,下面继续介绍
1.4 如何运行Java程序?
-
把代码保存为
HelloWorld.java -
打开命令行,输入:
javac HelloWorld.java(编译) -
再输入:
java HelloWorld(运行) -
看到"Hello, World!"就成功了!
-
这个是编译和运行,但是idea中只需要
都可以运行
成功输出
一、Java程序基础
1.1 第一个Java程序
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
1.2 注释
- 单行注释:
// 这是单行注释 - 多行注释:
/* 这是多行注释 */ - 文档注释:
/** 这是文档注释 */
// 单行注释示例
public class CommentExample {
/*
* 多行注释示例
* 可以写多行说明
*/
public static void main(String[] args) {
System.out.println("注释示例"); // 行尾注释
}
}
1.3 关键字
Java中具有特殊含义的保留字,全部小写:
-
public、class、static、void、int、if、for、while等这些是不能设置变量之类的使用这个保留的关键字,会报错
1.4 标识符命名规则
- 组成:字母、数字、
$、_ - 规则:
- 不能以数字开头
- 不能是关键字
- 区分大小写
// 正确的标识符
int age;
String userName;
double $price;
int _count;
// 错误的标识符
int 123age; // 数字开头
String class; // 关键字
1.5 命名规范
- 类名:大驼峰,如
StudentInfo - 方法名:小驼峰,如
getStudentName - 变量名:小驼峰,如
studentAge - 常量名:全大写,下划线分隔,如
MAX_VALUE - 包名:全小写,如
com.example.anfioo
二、变量与数据类型
2.1 变量声明与初始化
// 声明变量
int age;
String name;
// 初始化变量
age = 20;
name = "张三";
// 声明并初始化
double price = 99.99;
boolean isStudent = true;
2.2 基本数据类型
整数类型
byte b = 100; // 1字节,范围:-128 ~ 127
short s = 1000; // 2字节,范围:-32768 ~ 32767
int i = 100000; // 4字节,范围:-2^31 ~ 2^31-1
long l = 100000L; // 8字节,范围:-2^63 ~ 2^63-1
浮点类型
float f = 3.14f; // 4字节,单精度
double d = 3.14159; // 8字节,双精度
字符类型
char c1 = 'A'; // 单个字符
char c2 = 65; // ASCII码
char c3 = '\u0041'; // Unicode编码
布尔类型
boolean flag1 = true;
boolean flag2 = false;
| 数据类型 | 关键字 | 占用字节 | 取值范围 | 代码示例 |
|---|---|---|---|---|
| 整数类型 | byte | 1 字节 | -128 ~ 127 | byte b = 100; |
| 整数类型 | short | 2 字节 | -32768 ~ 32767 | short s = 1000; |
| 整数类型 | int | 4 字节 | -2³¹ ~ 2³¹-1 | int i = 100000; |
| 整数类型 | long | 8 字节 | -2⁶³ ~ 2⁶³-1 | long l = 100000L; |
| 浮点类型 | float | 4 字节 | 单精度 | float f = 3.14f; |
| 浮点类型 | double | 8 字节 | 双精度 | double d = 3.14159; |
| 字符类型 | char | 2 字节 | 0 ~ 65535 | char c1 = 'A';char c2 = 65;char c3 = '\u0041'; |
| 布尔类型 | boolean | 1 字节 | true / false | boolean flag1 = true;boolean flag2 = false; |
2.3 引用数据类型
String str = "Hello Java"; // 字符串
int[] arr = new int[5]; // 数组
2.4 类型转换
自动类型转换(隐式转换)
int a = 100;
double b = a; // int自动转换为double
byte x = 10;
int y = x; // byte自动转换为int
强制类型转换(显式转换)
double d = 3.14;
int i = (int)d; // 强制转换为int,结果为3
long l = 100L;
int j = (int)l; // 强制转换为int
三、运算符
3.1 算术运算符
int a = 10, b = 3;
System.out.println(a + b); // 13
System.out.println(a - b); // 7
System.out.println(a * b); // 30
System.out.println(a / b); // 3(整数除法)
System.out.println(a % b); // 1(取余)
3.2 自增自减运算符
int count = 5;
count++; // count变成6(先使用后加1)
++count; // count变成7(先加1后使用)
count--; // count变成6
--count; // count变成5
int y = 10;
int z = y++ + 5; // z = 15, y = 11
int w = ++y + 5; // w = 17, y = 12
++/--在前 → 先运算再使用;++/--在后 → 先使用再运算,这个要自己用下才理解
3.3 赋值运算符
int money = 100;
money += 50; // 相当于 money = money + 50,现在money=150
money -= 30; // 相当于 money = money - 30,现在money=120
money *= 2; // 相当于 money = money * 2,现在money=240
money /= 4; // 相当于 money = money / 4,现在money=60
3.4 比较运算符
int a = 10, b = 20;
System.out.println(a == b); // false
System.out.println(a != b); // true
System.out.println(a > b); // false
System.out.println(a < b); // true
System.out.println(a >= 10); // true
System.out.println(b <= 20); // true
3.5 逻辑运算符
boolean x = true, y = false;
System.out.println(x && y); // false(逻辑与)
System.out.println(x || y); // true(逻辑或)
System.out.println(!x); // false(逻辑非)
// 短路与(&&)和短路或(||)
int a = 10;
if (a > 5 || a / 0 > 1) { // 不会报错,因为短路
System.out.println("短路或");
}
3.6 三元运算符
int score = 85;
String result = score >= 60 ? "及格" : "不及格";
System.out.println(result); // 输出:及格
int max = (10 > 5) ? 10 : 5; // max = 10
三元运算符的核心用处 可以简化
if-else分支语句,用一行代码实现简单的二选一逻辑,省略if、else等关键词,让代码更简洁紧凑。对比示例: // 三元运算符写法(一行搞定) String result = score >= 60 ? "及格" : "不及格";
// 等价的 if-else 写法(多行代码) String result; if (score >= 60) { result = "及格"; } else { result = "不及格"; }
四、流程控制
流程控制用于按指定逻辑顺序执行代码,分为 顺序结构、分支结构、循环结构 三大类,配合跳转语句可灵活控制执行流程。
4.1 顺序结构
核心特点:代码从上到下、从左到右依次执行,是最基础的执行流程。
// 代码按顺序执行,先输出第一步,再第二步,最后第三步
System.out.println("第一步");
System.out.println("第二步");
System.out.println("第三步");
顺序结构是所有程序的基础,所有分支、循环内部的代码块,本质上也是按顺序执行的。
4.2 分支结构
根据条件判断,选择执行不同的代码块,分为 if 系列和 switch 两种。
4.2.1 if 语句
适合复杂条件判断(范围、多条件组合),支持单分支、双分支、多分支。
int score = 85;
// 多分支 if-else if-else
if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
if后的条件表达式必须返回 boolean 类型(true/false)。- 多分支判断时,条件是互斥的,一旦某个条件满足,后续条件不会再判断。
- 单个语句块的
{}可以省略,但推荐始终加上,避免代码歧义。
4.2.2 switch 语句
适合固定值匹配(如枚举、常量),代码可读性比多分支 if 更高。
int day = 3;
switch (day) {
case 1:
System.out.println("星期一");
break; // 跳出 switch,避免穿透
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
default: // 所有 case 都不匹配时执行
System.out.println("周末");
}
- case 穿透问题:如果省略
break,会从匹配的 case 开始,依次执行后续所有 case 的代码,直到遇到break或switch结束。switch支持的类型:byte/short/int/char及其包装类、String(Java 7+)、枚举类型。default位置不固定,推荐放在最后;即使所有 case 都匹配,default也不会执行。
4.3 循环结构
重复执行一段代码,直到满足终止条件,分为 for、while、do-while 三种。
4.3.1 for 循环
适合已知循环次数的场景,初始化、条件判断、步进操作集中在一行,结构清晰。
// 场景1:打印1-10
for (int i = 1; i <= 10; i++) { // 初始化; 循环条件; 步进
System.out.println(i);
}
// 场景2:计算1-100的和
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i; // 等价于 sum = sum + i
}
System.out.println("1-100的和:" + sum); // 输出 5050
for循环的三个表达式都可以省略:for(;;)会变成死循环,需配合break跳出。- 初始化的变量
i是局部变量,仅在循环体内有效。
4.3.2 while 循环
适合未知循环次数的场景,先判断条件,再执行循环体。
// 场景1:打印1-5
int i = 1; // 初始化循环变量
while (i <= 5) { // 循环条件
System.out.println(i);
i++; // 步进操作,避免死循环
}
// 场景2:计算5的阶乘(5! = 5×4×3×2×1)
int num = 5;
int factorial = 1;
while (num > 0) {
factorial *= num; // 等价于 factorial = factorial * num
num--;
}
System.out.println("5的阶乘:" + factorial); // 输出 120
若循环条件一开始就为
false,while循环一次都不会执行;务必在循环体内修改循环变量,否则会陷入死循环。
4.3.3 do-while 循环
至少执行一次循环体,再判断条件,适合需要“先执行,后判断”的场景。
int count = 0;
do {
System.out.println("执行次数:" + (count + 1));
count++;
} while (count < 3); // 循环条件
do-while循环的末尾必须加分号;,这是语法规定,容易遗漏。
4.4 跳转语句
用于控制循环或方法的执行流程,包括 break、continue、return。
// 1. break:跳出当前所在的循环/switch
System.out.println("=== break 示例 ===");
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break; // 当i=5时,直接跳出for循环
}
System.out.println(i); // 输出 1-4
}
// 2. continue:跳过本次循环,直接进入下一次循环判断
System.out.println("=== continue 示例 ===");
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue; // 跳过i=3的情况,不执行后续输出
}
System.out.println(i); // 输出 1,2,4,5
}
// 3. return:结束当前方法,无论后面还有多少代码都不会执行
public static void testReturn() {
System.out.println("=== return 示例 ===");
for (int i = 1; i <= 5; i++) {
if (i == 3) {
return; // 直接结束testReturn方法
}
System.out.println(i); // 输出 1,2
}
System.out.println("这行不会执行"); // 永远不会被执行
}
// 调用方法
testReturn();
break可以搭配标签跳出多层嵌套循环(如outer: for(...) { ... break outer; })。continue只能跳过当前循环,不能跳出循环;同样支持标签,跳过指定层级的循环。return不仅能结束循环,还会直接结束整个方法,是三者中“威力最大”的跳转语句。
4.5 嵌套循环
一个循环体内包含另一个完整的循环,常用于多维数据遍历(如矩阵、九九乘法表)。
// 打印九九乘法表
for (int i = 1; i <= 9; i++) { // 外层循环:控制行数
for (int j = 1; j <= i; j++) { // 内层循环:控制每行的列数
System.out.print(j + "×" + i + "=" + (i * j) + "\t"); // \t 制表符,对齐格式
}
System.out.println(); // 换行,开始下一行
}
- 嵌套循环的执行顺序:外层循环执行1次,内层循环执行全部次数,再回到外层循环的下一次。
- 尽量减少嵌套层级(推荐不超过3层),否则会降低代码可读性和执行效率。
- 可以用
break + 标签直接跳出外层循环,避免多层break的冗余判断。
五、方法(函数)
方法是完成特定功能的代码块,可以重复调用,让代码更简洁、复用性更强、便于维护。
5.1 方法定义与调用
概念
- 方法:具有独立功能的代码段,可以被重复调用
- 定义格式:
修饰符 返回值类型 方法名(参数列表) { 方法体; return; } - 调用方式:直接调用 / 赋值调用 / 输出调用
public class MethodExample {
// 无参数无返回值的方法
public static void sayHello() {
System.out.println("Hello!");
}
// 有参数无返回值的方法
public static void greet(String name) {
System.out.println("你好," + name);
}
// 有参数有返回值的方法
public static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
sayHello(); // 直接调用
greet("张三"); // 传递参数调用
int result = add(10, 20); // 赋值调用
System.out.println("10+20=" + result);
System.out.println(add(5, 7)); // 输出调用
}
}
- void 表示无返回值,不需要写 return
- 有返回值的方法必须用 return 带回结果
- 方法必须被调用才会执行,不会自动运行
- 方法只能定义在类中,不能嵌套定义
5.2 方法重载
概念
在同一个类中,方法名相同,但参数列表不同,这就是方法重载。
判定条件
- 参数个数不同
- 参数类型不同
- 参数顺序不同 与返回值类型无关!
public class OverloadExample {
// 方法1:两个int相加
public static int add(int a, int b) {
return a + b;
}
// 方法2:三个int相加(参数个数不同)
public static int add(int a, int b, int c) {
return a + b + c;
}
// 方法3:两个double相加(参数类型不同)
public static double add(double a, double b) {
return a + b;
}
public static void main(String[] args) {
System.out.println(add(10, 20)); // 调用方法1
System.out.println(add(10, 20, 30)); // 调用方法2
System.out.println(add(10.5, 20.5)); // 调用方法3
}
}
- 方法重载只看方法名和参数列表
- 返回值不同不算重载
- 好处:使用同一个方法名完成相似功能,降低记忆成本
5.3 递归方法
概念
方法自己调用自己,称为递归。 必须有出口(结束条件),否则会出现栈溢出错误。
public class RecursionExample {
// 计算阶乘(递归实现)
public static int factorial(int n) {
if (n == 0 || n == 1) { // 递归出口
return 1;
}
return n * factorial(n - 1);
}
// 计算斐波那契数列
public static int fibonacci(int n) {
if (n == 1 || n == 2) { // 递归出口
return 1;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
public static void main(String[] args) {
System.out.println("5的阶乘:" + factorial(5));
System.out.println("第6个斐波那契数:" + fibonacci(6));
}
}
- 递归必须有出口,否则会栈溢出
- 递归层级不宜过深,否则效率低、耗内存
- 适合:阶乘、斐波那契、树遍历、文件搜索等数学/分治问题
递归 = 自己调用自己 + 明确结束条件 公式:
问题 = 子问题 + 出口这个是很重要的算法会用到的地方
六、数组
数组就是一个装数据的容器,专门用来存 相同类型 的数据,比如存全班同学的成绩、存一组数字。 它的特点是:长度固定(一旦创建,不能变多或变少),通过位置访问(每个数据都有自己的编号)。
6.1 数组声明与初始化
简单说,就是 创建数组 + 存数据,有三种常用方式,根据需求选就行。
// 方式1:动态初始化 → 先指定能装多少个,后面再填数据
// 比如创建一个能装5个整数的数组,初始时里面全是0
int[] arr1 = new int[5];
// 方式2:静态初始化 → 直接把要存的数据写进去,不用指定长度
// 下面这个数组就装了5个数字,长度自动是5
int[] arr2 = {1, 2, 3, 4, 5};
// 方式3:先声明,后赋值 → 适合先定义数组,后面再确定存什么数据
int[] arr3;
arr3 = new int[]{10, 20, 30}; // 这里不用写长度
// 给数组赋值、取值
arr1[0] = 100; // 给数组第1个位置存100(数组的位置从0开始算)
System.out.println(arr2[2]); // 取数组第3个位置的值,输出 3
- 数组的位置编号从0开始,比如长度为5的数组,位置是 0、1、2、3、4,没有5!
- 动态初始化时,整数数组默认装0,字符串数组默认装
null(空)。- 直接写
{...}只能在创建数组时用,分开写必须加new int[]。
6.2 数组遍历
遍历就是把数组里的每个数据都看一遍、用一遍,两种简单方法,新手优先记第一种。
int[] numbers = {10, 20, 30, 40, 50};
// 方式1:普通for循环 → 能知道数据在哪个位置,还能修改数据
// length 就是数组的长度,直接用就行
for (int i = 0; i < numbers.length; i++) {
System.out.println("第" + (i+1) + "个数据:" + numbers[i]);
}
// 方式2:增强for循环 → 代码更简单,适合只看数据、不修改的场景
for (int num : numbers) {
System.out.println("数据值:" + num);
}
numbers.length是数组的“长度属性”,直接写就行,别写成length()!- 增强for循环不用记位置,写起来快,但没法修改原数组的数字。
- 想改数组里的数据,就用普通for循环。
6.3 数组常见操作
数组最常用的就是 找最值、求和、反转、找数据,都是新手必学的基础功能。
6.3.1 求最大值和最小值
核心思路:先假设第一个数是最大/最小的,然后挨个比,遇到更大/更小的就替换。
int[] scores = {85, 92, 78, 95, 88};
int max = scores[0]; // 先假设第一个数是最高分
int min = scores[0]; // 先假设第一个数是最低分
// 从第二个数开始比,省得重复比第一个
for (int i = 1; i < scores.length; i++) {
if (scores[i] > max) {
max = scores[i]; // 发现更高的,就更新最高分
}
if (scores[i] < min) {
min = scores[i]; // 发现更低的,就更新最低分
}
}
System.out.println("最高分:" + max); // 输出 95
System.out.println("最低分:" + min); // 输出 78
别一上来就写
int max = 0;!如果数组里全是负数(比如-5, -10),0就不是最大值了。
6.3.2 数组求和与平均值
核心思路:先把所有数加起来,总和除以个数就是平均值(注意算平均值时要转成小数)。
int[] numbers = {10, 20, 30, 40, 50};
int sum = 0; // 总和从0开始加
for (int num : numbers) {
sum += num; // 把每个数都加到总和里
}
// 算平均值时,要把sum转成小数,不然会舍去小数部分(比如 151/5 会算成30,不是30.2)
double average = (double) sum / numbers.length;
System.out.println("总和:" + sum); // 输出 150
System.out.println("平均值:" + average); // 输出 30.0
关键一步:
(double) sum是把整数转成小数,这样除法结果才是小数。
6.3.3 数组反转
核心思路:首尾交换!比如第1个和最后1个换,第2个和倒数第2个换,直到中间。
int[] arr = {1, 2, 3, 4, 5};
System.out.println("原数组:");
for (int num : arr) {
System.out.print(num + " "); // 输出 1 2 3 4 5
}
// 反转核心代码:i是开头位置,j是结尾位置
for (int i = 0, j = arr.length - 1; i < j; i++, j--) {
int temp = arr[i]; // 临时存一下开头的数
arr[i] = arr[j]; // 把结尾的数放到开头
arr[j] = temp; // 把临时存的数放到结尾
}
System.out.println("\n反转后:");
for (int num : arr) {
System.out.print(num + " "); // 输出 5 4 3 2 1
}
循环条件是
i < j,别写成i <= j!不然中间的数会被换回去,等于没反转。
6.3.4 数组查找(找某个数在不在)
核心思路:挨个找,找到就说“在”,并告诉位置;找不到就说“不在”。
int[] arr = {10, 20, 30, 40, 50};
int target = 30; // 要找的数
boolean found = false; // 标记有没有找到
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
System.out.println("找到" + target + "啦,位置是:" + i); // 输出位置2
found = true;
break; // 找到就别找了,省时间
}
}
if (!found) {
System.out.println("没找到" + target);
}
找到后一定要写
break,不然程序会把整个数组都遍历完,没必要。
6.4 二维数组
二维数组就是“数组里套数组”,可以理解成一个表格,有行和列,比如存全班同学的各科成绩。
// 方式1:创建一个3行4列的表格,初始全是0
int[][] matrix = new int[3][4];
// 方式2:直接填数据,每行可以不一样长(比如第一行3个,第三行2个)
int[][] scores = {
{85, 90, 78}, // 第一行:张三的语文、数学、英语成绩
{92, 88, 95}, // 第二行:李四的三科成绩
{76, 85} // 第三行:王五的两科成绩
};
// 取值:先写行,再写列 → 比如取李四的英语成绩(第二行第三列)
System.out.println("李四的英语成绩:" + scores[1][2]); // 输出95
// 遍历:用两层循环,外层遍历行,内层遍历列
for (int i = 0; i < scores.length; i++) { // scores.length 是行数
for (int j = 0; j < scores[i].length; j++) { // scores[i].length 是第i行的列数
System.out.print(scores[i][j] + "\t"); // \t 让表格对齐
}
System.out.println(); // 每行结束后换行
}
- 二维数组的位置是
数组名[行号][列号],行和列的编号都从0开始。- 行数就是
数组名.length,某一行有多少列,就用数组名[行号].length。
6.5 数组常见异常(新手必避坑)
数组最容易踩两个坑,运行时会报错,记住怎么防就行!
int[] arr = {1, 2, 3};
int[] arr2 = null; // 这个数组是空的,没装任何数据
// 坑1:索引越界 → 想访问的位置不存在
// System.out.println(arr[5]); // 错误!arr只有3个数据,位置是0、1、2,没有5
// 坑2:空指针异常 → 数组是空的,却想拿它的长度或数据
// System.out.println(arr2.length); // 错误!arr2是null,没有长度
// 避坑方法:先判断,再使用
if (arr != null && arr.length > 5) { // 先看数组是不是空的,再看长度够不够
System.out.println(arr[5]);
} else {
System.out.println("数组是空的,或者长度不够");
}
- 索引越界:别访问超出数组长度的位置,循环时用
i < 数组名.length当条件。- 空指针异常:用数组之前,先判断它是不是
null。
七、输入输出
输入输出(I/O)是程序和用户交互的核心,控制台输出是程序给用户展示信息,键盘输入是用户给程序传递数据。
这里会用到 java.util.Scanner 工具类,你可以把类想象成“工具包”,方法就是包里的工具,导入类才能使用对应的工具实现输入功能。
7.1 控制台输出
三种常用输出方式,对应不同的使用场景,核心是 System.out 这个“输出工具”。
// 1. print:输出内容后不换行,光标停在当前行末尾
System.out.print("不换行输出");
System.out.print(" → 看,我和上面的内容在一行\n"); // \n 是换行符,手动换行
// 2. println:输出内容后自动换行,最常用
System.out.println("换行输出");
System.out.println("我在新的一行");
// 3. printf:格式化输出,按指定格式展示数据(比如保留小数位数)
// 格式说明符:%s 代表字符串,%d 代表整数,%.2f 代表保留2位小数的浮点数
System.out.printf("格式化输出:%s今年%d岁\n", "张三", 20);
// 格式化输出示例:控制小数位数
int age = 20;
double score = 95.5;
// %.2f 表示把score格式化为保留2位小数的浮点数,这里会输出 95.50
System.out.printf("年龄:%d,分数:%.2f\n", age, score);
- 日常打印信息优先用
println,自动换行更省心;- 需要精准控制格式(比如保留小数、对齐文本)用
printf;
7.2 键盘输入
想要读取用户从键盘输入的内容,必须用 Scanner 类——这个类就是专门的“输入工具包”。
你可以这样理解:
- 类(Scanner) = 一个带各种“输入工具”的工具箱;
- 方法(nextLine()、nextInt()) = 工具箱里的螺丝刀、扳手,各有各的用途(读字符串、读整数);
- import 语句 = 打开工具箱的钥匙,没有钥匙就用不了里面的工具。
// 导入 Scanner 工具包 → 拿到打开工具箱的钥匙
// 这行必须写在代码最上面(类定义之前)
import java.util.Scanner;
public class InputExample {
public static void main(String[] args) {
// 创建 Scanner 对象 → 打开工具箱,准备用工具
// System.in 表示“从键盘获取输入”
Scanner scanner = new Scanner(System.in);
System.out.print("请输入姓名:");
// nextLine():读取一整行字符串(包括空格),适合读姓名
String name = scanner.nextLine();
System.out.print("请输入年龄:");
// nextInt():读取整数,专门用来接收数字
int age = scanner.nextInt();
System.out.print("请输入身高(米):");
// nextDouble():读取小数(双精度浮点数)
double height = scanner.nextDouble();
// 输出用户输入的信息,验证是否读取成功
System.out.println("--- 输入信息 ---");
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
System.out.println("身高:" + height + "米");
// 关闭 Scanner → 用完工具箱要关上,释放资源
scanner.close();
}
}
- 工具和用途要匹配:读字符串用
nextLine(),读整数用nextInt(),读小数用nextDouble(),别混用;- 注意
nextLine()的坑:如果前面用了nextInt()/nextDouble(),再用nextLine()会读取到“空行”,解决方法是多写一行scanner.nextLine()吸收换行符;- 用完记得关:调用
scanner.close()是好习惯,避免占用系统资源。
- 输入的数据类型要和方法匹配!比如用
nextInt()时输入字母,程序会直接报错;import java.util.Scanner;这行不能漏,漏了就会提示“找不到 Scanner 类”。
八、综合示例
这里的两个小案例,整合了数组、循环、分支、键盘录入、随机数等基础知识点,适合新手理解 Java 基础语法的实际应用。
8.1 学生成绩管理系统(简化版)
核心知识点:数组存储数据、for循环遍历、键盘录入Scanner、最值查找、平均值计算
import java.util.Scanner; // 导入键盘录入工具类,这是基础IO知识点
// 学生成绩管理系统:实现录入姓名和成绩、计算平均分、找最高分最低分
public class StudentGradeSystem {
public static void main(String[] args) {
// 1. 创建Scanner对象,用于接收用户从控制台输入的数据
Scanner scanner = new Scanner(System.in);
// 提示用户输入学生人数,这是动态确定数组长度的关键
System.out.print("请输入学生人数:");
int studentCount = scanner.nextInt();
// 2. 定义两个数组,分别存储学生姓名和对应的成绩
// 数组长度由用户输入的人数决定,体现数组动态初始化的用法
String[] names = new String[studentCount]; // 字符串数组存姓名
int[] scores = new int[studentCount]; // int数组存成绩
// 3. 用for循环遍历数组,逐个录入学生信息
// 这里用到了普通for循环(带索引),因为需要给数组元素赋值
for (int i = 0; i < studentCount; i++) {
System.out.print("请输入第" + (i+1) + "个学生的姓名:");
names[i] = scanner.next(); // 给姓名数组的第i个位置赋值
System.out.print("请输入" + names[i] + "的成绩:");
scores[i] = scanner.nextInt(); // 给成绩数组的第i个位置赋值
}
// 4. 计算所有学生的成绩总和,用于后续算平均分
// 这里用到增强for循环,因为只需要读取成绩,不需要索引
int total = 0; // 总和初始化为0
for (int score : scores) {
total += score; // 累加每个学生的成绩
}
// 计算平均分:强制转换为double,避免整数除法丢失小数
double average = (double) total / studentCount;
// 5. 查找最高分和最低分,以及对应的学生姓名
// 初始化最值为数组第一个元素,避免出现0值错误
int maxScore = scores[0];
int minScore = scores[0];
String maxName = names[0];
String minName = names[0];
// 从第二个元素开始遍历比较,节省一次循环
for (int i = 1; i < studentCount; i++) {
// 分支结构if:判断当前成绩是否大于最高分
if (scores[i] > maxScore) {
maxScore = scores[i]; // 更新最高分
maxName = names[i]; // 更新最高分对应的姓名
}
// 分支结构if:判断当前成绩是否小于最低分
if (scores[i] < minScore) {
minScore = scores[i]; // 更新最低分
minName = names[i]; // 更新最低分对应的姓名
}
}
// 6. 输出统计结果,格式化打印信息
System.out.println("\n=== 成绩统计结果 ===");
System.out.println("平均分:" + average);
System.out.println("最高分:" + maxName + " - " + maxScore + "分");
System.out.println("最低分:" + minName + " - " + minScore + "分");
// 关闭Scanner,释放资源,养成良好编程习惯
scanner.close();
}
}
8.2 猜数字游戏
核心知识点:随机数生成Random、do-while循环(先执行后判断)、if-else分支、计数器
import java.util.Random; // 导入随机数生成工具类
import java.util.Scanner; // 导入键盘录入工具类
// 猜数字游戏:生成1-100的随机数,用户猜数字,给出大/小提示,直到猜对
public class GuessNumberGame {
public static void main(String[] args) {
// 1. 创建Random对象,用于生成随机数
Random random = new Random();
// 2. 创建Scanner对象,用于接收用户猜测的数字
Scanner scanner = new Scanner(System.in);
// 生成1-100的随机数:nextInt(100)生成0-99,+1后变成1-100
int target = random.nextInt(100) + 1;
int guess; // 存储用户每次猜测的数字
int attempts = 0; // 计数器:记录用户猜的次数
// 游戏欢迎语
System.out.println("欢迎来到猜数字游戏!");
System.out.println("我已经想好了一个1-100之间的数字,请开始猜吧!");
// 3. 用do-while循环实现游戏逻辑:至少执行一次(先猜再判断)
// 这是do-while循环的典型场景:需要先执行循环体,再判断条件
do {
System.out.print("请输入你的猜测:");
guess = scanner.nextInt(); // 接收用户输入的猜测值
attempts++; // 每猜一次,计数器加1
// 4. 用if-else if-else分支结构,根据猜测结果给出提示
if (guess > target) {
System.out.println("猜大了!");
} else if (guess < target) {
System.out.println("猜小了!");
} else {
// 猜对了,输出恭喜信息和猜测次数
System.out.println("恭喜你,猜对了!");
System.out.println("你一共猜了" + attempts + "次");
}
} while (guess != target); // 循环条件:没猜对就继续猜
// 关闭资源
scanner.close();
}
}
九、常见问题与练习
9.1 常见错误
-
忘记分号:
System.out.println("Hello")❌ -
大小写错误:
system.out.println❌ -
括号不匹配:
if (x > 5 {❌ -
数组越界:访问不存在的索引
-
空指针:使用未初始化的对象
但是一般使用idea这些都是自动化的,并且有完美的提示
鼠标移动到这个红色的部分
非常清晰的就是展示有什么错误
总结
本指南涵盖了Java基础语法的核心内容,适合初学者系统学习。建议按照以下顺序学习,可以结合ai进行学习:
- 基础语法:变量、数据类型、运算符
- 流程控制:条件判断、循环
- 方法:函数定义、调用、重载
- 数组:一维数组、二维数组
- 综合应用:结合所学知识解决实际问题
学习编程最重要的是实践,建议在学习每个知识点后都编写相应的代码进行练习。遇到问题时,可以查阅官方文档或在线资源,逐步培养解决问题的能力。
祝大家学习顺利,早日掌握Java编程!