文章目录
- 前置知识
- [Java 简介](#Java 简介)
-
- [一、Java 核心三大特性(核心设计基石)](#一、Java 核心三大特性(核心设计基石))
- [二、Java 技术体系(三大核心平台,覆盖全开发场景)](#二、Java 技术体系(三大核心平台,覆盖全开发场景))
- [三、Java 典型应用领域](#三、Java 典型应用领域)
- [四、Java 语言的核心优势](#四、Java 语言的核心优势)
- [五、Java 版本迭代与现状](#五、Java 版本迭代与现状)
- [六、Java 开发的核心环境](#六、Java 开发的核心环境)
- [Java 入门](#Java 入门)
- [JavaSE 基础](#JavaSE 基础)
- [Java 控制流程](#Java 控制流程)
-
- 用户交互Scanner
- [Java 的三大基本程序结构](#Java 的三大基本程序结构)
-
- 顺序结构
- 选择结构
-
- [if 选择结构语法](#if 选择结构语法)
- [switch 选择结构语法](#switch 选择结构语法)
- 注意
- 穿透现象的利用(多值共用代码块)
- [JDK 14 新特性:switch 表达式(简化写法)](#JDK 14 新特性:switch 表达式(简化写法))
- 选型核心原则
- 循环结构
-
- [while 循环结构](#while 循环结构)
- [do...while 循环结构](#do...while 循环结构)
- [for 循环结构](#for 循环结构)
- [增强 for 循环(for-each)](#增强 for 循环(for-each))
- [循环控制关键字 break & continue](#循环控制关键字 break & continue)
-
- [break 关键字:强制终止循环](#break 关键字:强制终止循环)
- [continue 关键字:跳过本次循环,继续下一次](#continue 关键字:跳过本次循环,继续下一次)
- [break & continue 核心区别对比](#break & continue 核心区别对比)
- 嵌套循环:循环中包含循环
- [Java 的方法](#Java 的方法)
前置知识
字节
- 位(bit)
是计算机内部数据存储的最小单位,只有 0 和 1 两种状态,用来表示一个二进制数位。例如 11001100 就是一个 8 位的二进制数。 - 字节(byte)
是计算机中数据处理的基本单位,习惯上用大写 B 表示。
换算关系:1B = 8bit,即 1 个字节由 8 个二进制位组成。 - 字符
指计算机中使用的字母、数字、文字和符号,比如 A、5、中、! 都属于字符。
存储单位换算
计算机存储容量的标准换算关系:
1Byte = 8bit
1024B = 1KB
1024KB = 1MB
1024MB = 1GB
转义字符
Java 转义字符以反斜杠 \ 开头,用于表示特殊字符或无法直接输入的字符(如换行、制表符等)。以下是常见转义字符及其用途。
常见转义字符列表
\t:水平制表符(Tab)\n:换行符(Newline)\r:回车符(Carriage Return)\\:反斜杠本身\":双引号(用于字符串内)\':单引号(用于字符内)\b:退格符(Backspace)\f:换页符(Form Feed)
java
public class EscapeSequences {
public static void main(String[] args) {
System.out.println("Hello\tWorld"); // 输出: Hello World(制表符)
System.out.println("Line1\nLine2"); // 输出: Line1 换行 Line2
System.out.println("C:\\Program\\Java"); // 输出: C:\Program\Java
System.out.println("He said, \"Hi\""); // 输出: He said, "Hi"
}
}
Unicode 转义
Java 支持 Unicode 转义,格式为 \uXXXX(4位十六进制数)。例如:
java
System.out.println("\u03A9"); // 输出希腊字母 Ω
注意事项
- 在正则表达式中需双重转义(如
\\d匹配数字)。 - 字符串中的换行符需根据操作系统调整(Windows 使用
\r\n,Linux/macOS 使用\n)。
通过合理使用转义字符,可以处理特殊字符或格式化文本输出。
Java 简介
Java 是由Sun Microsystems(后被 Oracle 收购)于 1995 年推出的面向对象、跨平台高级编程语言,由詹姆斯・高斯林(James Gosling)及其团队研发,核心设计理念围绕 "简单、安全、跨平台、高性能" 展开,目前已成为全球最主流的编程语言之一,广泛应用于企业级开发、移动开发、大数据等多个领域。
一、Java 核心三大特性(核心设计基石)
Java 的跨平台能力和核心优势,核心依托于三大核心特性,也是其区别于其他语言的关键:
- 一次编写,到处运行(Write Once, Run Anywhere - WORA)
这是 Java 最标志性的特性,实现原理是Java 程序并非直接编译为操作系统的机器码,而是先由 javac 编译器编译为与平台无关的字节码(Bytecode)(文件后缀 .class),再由不同操作系统上对应的Java 虚拟机(JVM, Java Virtual Machine)解释 / 编译执行字节码。
开发者只需编写一套代码,无需针对 Windows、Linux、macOS 等不同系统做修改;
不同系统只需安装对应的JVM(虚拟机),即可运行相同的字节码文件,真正实现跨平台。 - 面向对象(Object-Oriented, OOP)
Java 是纯面向对象的编程语言(除基本数据类型外,一切皆对象),完全遵循面向对象的四大核心原则:封装、继承、多态、抽象,通过类(Class)和对象(Object)组织代码,大幅提升代码的可复用性、可维护性和扩展性,适合开发大型、复杂的软件系统。 - 自动内存管理(垃圾回收 - Garbage Collection, GC)
Java 摒弃了 C/C++ 中手动管理内存的方式(手动malloc分配 /free释放),由 JVM 的垃圾回收器 自动监控并回收程序中不再使用的内存空间(无引用的对象),从根源上减少了内存泄漏和空指针异常等常见内存问题,降低了开发门槛和程序出错概率。
注:开发者可通过 JVM 参数调优垃圾回收策略,平衡内存使用和程序性能。
二、Java 技术体系(三大核心平台,覆盖全开发场景)
Java 并非单一语言,而是一套完整的技术体系,根据应用场景分为三大核心平台,适配从嵌入式到大型分布式系统的所有开发需求:
- Java SE(Java Standard Edition - 标准版)
核心基础
Java 技术的基础核心,包含 Java 核心语法、基础类库(集合、IO、多线程、网络编程等)、JVM、编译器等核心组件,是其他两个平台的基础。主要用于开发桌面应用(如 Swing/JavaFX 程序)、控制台程序,以及为 Java EE/Java ME 提供底层支持。 - Java EE(Java Platform, Enterprise Edition - 企业版)
基于 Java SE 扩展的企业级开发平台,提供了一系列针对企业级应用的标准和技术规范(如 Servlet、JSP、EJB、Spring、MyBatis 等),专门用于开发分布式、高可用、高并发的企业级应用,如电商平台、金融系统、后台管理系统、大型网站后端等,是 Java 在企业开发领域的核心应用方向。 - Java ME(Java Micro Edition - 微型版)
基本不用
基于 Java SE 精简的嵌入式 / 移动开发平台,针对资源受限的设备(如嵌入式设备、智能家电、早期功能手机)设计,核心是轻量级的类库和 JVM。随着 Android 的兴起,其移动开发场景逐渐被替代,但仍在嵌入式领域有一定应用。
三、Java 典型应用领域
依托跨平台、稳定、安全、高性能的特性,Java 的应用覆盖几乎所有软件开发领域,是工业级开发的 "主力军",主要应用场景包括:
企业级后端开发:最核心的应用领域,基于 Spring Boot、Spring Cloud 等框架开发分布式微服务系统,支撑电商、金融、政务、物流等行业的核心业务;
Android 应用开发:Android 系统的底层开发语言为 Java(目前 Kotlin 为官方推荐,但仍兼容 Java),几乎所有 Android App 的核心逻辑都可通过 Java 实现;
大数据开发:大数据生态的核心框架(Hadoop、Spark、Flink、HBase 等)均由 Java 编写,大数据开发中的核心业务逻辑开发、框架二次开发也主要使用 Java;
桌面应用开发:通过 Swing、JavaFX 等技术开发跨平台的桌面客户端(如办公软件、开发工具、工业控制软件);
嵌入式开发:基于 Java ME 开发智能家电、物联网设备、工业嵌入式系统;
云原生开发:结合 Docker、K8s、Spring Cloud Alibaba 等技术,开发云原生微服务、容器化应用。
四、Java 语言的核心优势
跨平台性:依托 JVM 和字节码,实现 "一次编写,到处运行",大幅降低多平台开发的成本;
面向对象:纯面向对象设计,代码结构清晰,可复用性和可维护性强,适合大型项目开发;
内存安全:自动垃圾回收机制,避免手动内存管理的错误,同时提供数组边界检查、空指针防护等机制,提升程序稳定性;
安全性高:内置安全管理器(Security Manager),可限制程序的资源访问(如文件、网络),同时字节码验证机制可防止恶意代码执行,适合开发金融、政务等对安全要求高的系统;
生态完善:拥有全球最丰富的开源生态,海量的第三方框架(Spring、MyBatis、Netty 等)、类库和工具,大幅提升开发效率,解决几乎所有开发场景的问题;
稳定性和高性能:经过二十多年的迭代优化,Java 虚拟机的即时编译(JIT)技术大幅提升了程序运行效率,同时语言本身的设计保证了程序的稳定性,可支撑 7×24 小时不间断运行的企业级系统;
跨领域兼容:可与 C/C++、Python、Go 等语言无缝集成,同时支持多种数据库(MySQL、Oracle、Redis 等),适配不同的技术栈;
社区和人才丰富:全球拥有庞大的开发者社区,遇到问题可快速找到解决方案;同时 Java 开发者基数大,企业易招聘到相关人才。
五、Java 版本迭代与现状
Java 自 1995 年发布以来,持续迭代优化,核心版本节点包括:
JDK 1.0(1996):首个正式版本,奠定核心语法和 JVM 基础;
JDK 5(2004):里程碑版本,引入泛型、注解、自动装箱、foreach 循环等核心特性,大幅提升开发效率;
JDK 8(2014):目前使用最广泛的 LTS(长期支持)版本,引入 Lambda 表达式、Stream API、函数式接口等,支持函数式编程,是企业开发的主流版本;
JDK 11(2018):新一代 LTS 版本,移除永久代、引入模块化(Module)、支持 HTTP/2,适合云原生开发;
JDK 17(2021):最新的主流 LTS 版本,优化模块化、增强安全性、提升性能,是目前推荐的新一代生产环境版本。
目前企业开发中,JDK 8 仍占主导地位(生态兼容最完善),JDK 11 和 JDK 17 的使用率正在快速提升,Oracle 对 LTS 版本提供长期的安全更新和技术支持,保障企业系统的稳定性。
六、Java 开发的核心环境
Java 开发的基础环境为 JDK(Java Development Kit - Java 开发工具包),它包含了开发 Java 程序所需的所有组件:
JRE(Java Runtime Environment - Java 运行时环境):包含 JVM、核心类库,是运行 Java 程序的基础(仅运行程序可只安装 JRE);
编译器(javac):将 Java 源代码(.java)编译为字节码(.class);
解释器(java):启动 JVM 并执行字节码文件;
其他工具(javadoc、jdb、javap 等):用于生成文档、调试程序、反编译字节码等。
开发者只需在电脑上安装对应系统的 JDK,配置环境变量后,即可通过命令行或 IDE(如 IntelliJ IDEA、Eclipse)进行 Java 开发。
Java 入门
JDK、JRE、JVM
JDK ⊃ JRE ⊃ JVM
- JVM(Java Virtual Machine):最底层的执行引擎,负责加载并执行 .class 字节码文件,是实现 "一次编写,到处运行" 的核心。
作用:屏蔽了不同操作系统的底层差异,让字节码可以在任何安装了 JVM 的系统上运行,是跨平台能力的核心。 - JRE(Java Runtime Environment):包含 JVM 和 Java 核心类库(如集合、IO、网络等),是运行 Java 程序的必要环境。
作用:提供了运行 Java 程序所需的基础环境,普通用户只需安装 JRE 就能运行已编译的 Java 程序。 - JDK(Java Development Kit):在 JRE 基础上增加了开发工具(如编译器 javac、打包工具 jar、文档生成工具 javadoc 等),是开发 Java 程序的完整工具包。
作用:面向开发者,包含了开发、编译、调试 Java 程序的所有工具,开发者必须安装 JDK 才能进行编码工作。
Java程序运行机制
Java 程序先经编译器 javac 把.java源文件编译成字节码.class文件。字节码由 JVM 加载,JVM 里类加载子系统负责找到并加载字节码,然后字节码被送到执行引擎,执行引擎可以采用解释执行(逐行解释执行字节码)或 JIT 即时编译(将频繁执行代码编译为机器码)方式运行,运行时数据区还会分配内存来存储程序运行的各种数据,像堆存对象、栈管方法调用等。
IDE
IDE 是集成开发环境(Integrated Development Environment)的简称,它把源代码编辑器、构建自动化工具、调试器等软件开发工具集成在一起,有些还包含编译器、解释器。能提高开发效率,常见的有用于 Java 开发的 Eclipse、IntelliJ IDEA 等。
第一个Java程序
java
public class HelloJava {
public static void main(String[] args){
System.out.print("Hello,World!");
}
}
public:访问修饰符,表示公共的,可被其他类访问。
class:定义类的关键字,一个 Java 程序基本单元。
HelloJava:类名,需与文件名一致(首字母大写规范)。
static:静态的,修饰方法表示可直接用类名调用。
void:表示方法无返回值。
main:主方法名,程序执行入口。
String[]:字符串数组类型。
args:数组名,可接收命令行参数 。
System:系统类,提供一些系统相关功能。
out:System类的标准输出对象。
print:输出方法,输出内容不换行。
JavaSE 基础
注释
Java中的注释有三种:
单行注释
java
int x = 10; // 这是一个单行注释
多行注释
java
/*
这是多行注释
可以包含多行内容
*/
System.out.println("Hello");
文档注释
java
/**
* 计算两个数的和
* @param a 第一个加数
* @param b 第二个加数
* @return 两数之和
*/
public int add(int a, int b) {
return a + b;
}
文档注释的标签
Java文档注释支持多种标准标签,用于规范化文档内容。常用标签包括:
- @param描述方法参数
java
@param parameterName 参数说明
- @return描述返回值
java
@return 返回值说明9
- @throws描述可能抛锚的异常
java
@throws ExceptionType 异常说明
- @see创建交叉引用
java
@see ClassName#methodName
- @deprecated标记已过时的方法
java
@deprecated 替代方案说明
- @since指明引入文本
java
@since versionNumber
生成API文档
使用Javadoc工具可以从文档注释生成HTML格式的API文档。在命令行运行:
bash
javadoc -d docDir SourceFiles.java
常用Javadoc选项包括:
-d指定输出目录
-author包含作者信息
-version包含版本信息
-encoding指定字符编码
IDE如IntelliJ IDEA和Eclipse都内置Javadoc支持,可通过图形界面生成文档。生成的文档包含类层次结构、方法详细说明和交叉引用等信息。
关键字
Java关键字是编程语言中预定义的保留字,具有特定功能,不能作为变量名、类名或方法名使用。Java共有50多个关键字,分为数据类型、流程控制、访问控制等类别。
数据类型关键字
基本类型:byte、short、int、long、float、double、char、boolean
引用类型:class、interface、enum
特殊值:null、true、false
流程控制关键字
条件语句:if、else、switch、case、default
循环语句:for、while、do
跳转语句:break、continue、return
访问控制关键字
public:全局可见
protected:包内及子类可见
private:仅类内可见
default(隐式):包内可见
类与对象关键字
class:定义类
new:创建对象实例
this:当前对象引用
super:父类引用
extends:继承
implements:实现接口
instanceof:类型检查
异常处理关键字
try:捕获异常代码块
catch:处理异常
finally:最终执行块
throw:抛出异常
throws:声明可能抛出的异常
修饰符关键字
static:类级别成员
final:不可修改的变量、方法或类
abstract:抽象类或方法
synchronized:线程同步
volatile:变量可见性
transient:序列化时忽略字段
native:本地方法
其他关键字
package:定义包
import:导入类
assert:断言检查
const(未使用):保留字
goto(未使用):保留字
注意事项
关键字严格区分大小写,例如class正确,Class不是关键字。
避免与保留字冲突,如var(Java 10后作为局部变量类型推断,非严格关键字)。
数据类型
Java是强类型语言:要求变量的使用严格符合规定,所有变量都必须先定义后使用
基本数据类型(Primitive Type)
Java中的基本数据类型是预定义的,由语言本身提供,共有8种。这些类型不依赖于任何类,直接存储值。
- 整数类型
byte: 8位,范围-128到127
short: 16位,范围-32,768到32,767
int: 32位,范围-2³¹到2³¹-1
long: 64位,范围-2⁶³到2⁶³-1(long类型后面要加L) - 浮点类型
float: 32位,单精度浮点数(float类型后面要加F)
double: 64位,双精度浮点数 - 字符类型
char: 16位,存储Unicode字符(一种国际字符编码标准)
注:Unicode为全球几乎所有语言的字符、符号、表情等都分配了唯一的数字编码(码点),解决了传统编码(如 ASCII、GBK)只能表示有限字符、不同编码间不兼容的问题。 - 布尔类型
boolean: 存储true或false
引用数据类型(Reference Data Types)
引用数据类型指向对象的引用,而非直接存储值。这些类型基于类或接口。
- 类类型
String: 字符串类
自定义类: 用户定义的类 - 数组类型
一维或多维数组,如int[]或String[][] - 接口类型
实现接口的类的对象
数据转换
Java中的数据类型转换分为 自动类型转换(隐式转换) 和 强制类型转换(显式转换) 两种。
自动类型转换(隐式转换)
自动类型转换发生在兼容的数据类型之间,且目标类型的范围大于源类型时,编译器会自动完成转换。
java
int a = 100;
long b = a; // 自动将int转换为long
自动转换规则:
byte → short → int → long → float → double
char → int → long → float → double
java
byte byteVal = 10;
short shortVal = byteVal; // byte自动转为short
int intVal = shortVal; // short自动转为int
float floatVal = intVal; // int自动转为float
double doubleVal = floatVal; // float自动转为double
注:

字符串 + xxx ,String --> 会将后面的数据转换成字符串
强制类型转换(显式转换)
当需要将范围大的数据类型转换为范围小的数据类型时,必须使用强制类型转换。语法是在变量前加上目标类型的括号
java
long a = 1000L; // long类型后面要加L
int b = (int) a; // 强制将long转为int
注:可能导致数据丢失或精度损失。对于超出目标类型范围的值,结果可能不符合预期。
java
double d = 123.456;
int i = (int) d; // i的值为123,小数部分丢失
int largeInt = 300;
byte smallByte = (byte) largeInt; // 结果为44(300超出byte范围,发生截断)
字符串与其他类型的转换
- 其他类型转字符串:
使用String.valueOf()方法或直接拼接:
java
int num = 42;
String str1 = String.valueOf(num); // "42"
String str2 = "" + num; // "42"
- 字符串转其他类型:
使用包装类的parseXxx()方法:
java
String str = "123";
int num = Integer.parseInt(str); // 123
double d = Double.parseDouble("3.14"); // 3.14
特殊类型转换
-
char与int的转换:
char可以自动转换为int(ASCII值):javachar c = 'A'; int ascii = c; // 65 -
int强制转为char:
javaint code = 97; char ch = (char) code; // 'a'
注意
- 不能对布尔值进行转换
- 不能把对象类型转换为不相干的类型
- 把高容量转化到低容量的时候,是强制转换
- 转换的时候可能存在内存溢出,或者精度问题
变量
Java变量是存储数据的基本单元,需先声明后使用。声明语法为:数据类型 变量名 = 值;
java
// 声明单个变量并赋值
int age = 20;
// 声明多个同类型变量,部分赋值
double height, weight = 65.5;
// 声明多个同类型变量并全部赋值
String name = "Alice", gender = "female";
变量的命名规则
- 以字母、_或$开头,不能以数字开头。
- 区分大小写,不能使用Java关键字(如class、public)。
- 推荐使用驼峰命名法(如studentName)。
变量的初始化
变量声明后可赋值,也可直接初始化:
java
int count = 10;
double price = 19.99;
boolean isActive = true;
变量的作用域
局部变量:在方法或代码块内声明,仅在其范围内有效。
成员变量:在类中声明,整个类中可用(实例变量或静态变量)。
常量
在Java中,常量是指一旦赋值后不能被修改的变量。通常使用final关键字声明,表示其值不可变。常量可以是基本数据类型(如int、double)或对象引用(如String)。
- 基本数据类型常量
java
final int MAX_VALUE = 100;
final double PI = 3.14159;
- 对象引用常量
java
final String MESSAGE = "Hello, World!";
- 静态常量(类常量)
结合static和final,通常用于全局常量:
java
public static final String DEFAULT_NAME = "Unknown";
注:final修饰的引用类型常量仅保证引用不变,对象内容可能可变(如final List仍可添加元素)。 编译时常量(如final int X = 10)会直接内联到代码中,运行时不会重复计算。 类常量通过类名直接访问,如ClassName.DEFAULT_NAME。
常量的命名规范
- 使用全大写字母,单词间用下划线分隔(如MAX_SIZE)。
- 名称应清晰表达其用途,避免魔法数字(如直接使用3.14)。
运算符
Java中的运算符用于执行各种操作,如算术运算、逻辑运算、赋值等。运算符可以分为以下几类:
算术运算符
+:加法
-:减法
*:乘法
/:除法
%:取模(取余)
++:自增(前缀或后缀)
--:自减(前缀或后缀)
关系运算符
==:等于
!=:不等于
>:大于
<:小于
>=:大于等于
<=:小于等于
逻辑运算符
&&:逻辑与 ---> 结果都为真---> 一假为假
java
(b&&a) // 如果b为假 ,后面就短路了,不会执行
||:逻辑或 ---> 一真为真 ---> 都假为假
!:逻辑非 ---> 真变假 ---> 假变真
位运算符
&:按位与
|:按位或
^:按位异或
~:按位取反
<<:左移
>>:右移(带符号)
>>>:无符号右移
java
int num1 = 5; // 二进制 0101
int num2 = 3; // 二进制 0011
System.out.println(num1 & num2); // 输出1 (0001)
System.out.println(num1 << 1); // 输出10 (1010)
赋值运算符
=:简单赋值
+=:加后赋值
-=:减后赋值
*=:乘后赋值
/=:除后赋值
%=:取模后赋值
<<=:左移后赋值
>>=:右移后赋值
&=:按位与后赋值
|=:按位或后赋值
^=:按位异或后赋值
条件运算符(三元运算符)
语法:条件 ? 表达式1 : 表达式2
如果条件为真,返回表达式1的值,否则返回表达式2的值。
instanceof运算符
用于检查对象是否是特定类的实例或其子类的实例。
java
String str = "Hello";
System.out.println(str instanceof String); // 输出true
优先级
运算符的优先级决定了表达式中运算的顺序。以下是从高到低的优先级:
- ()、[]、.(括号、数组下标、成员访问)
- !、~、++、--(逻辑非、位非、自增、自减)
- *、/、%(乘、除、取模)
- +、-(加、减)
- <<、>>、>>>(移位)
- <、<=、>、>=、instanceof(关系运算)
- ==、!=(相等性)
- &(按位与)
- ^(按位异或)
- |(按位或)
- &&(逻辑与)
- ||(逻辑或)
- ?:(条件运算符)
- =、+=、-=等(赋值)
包机制
Java 包(Package)是一种用于组织类和接口的命名空间机制,主要解决类名冲突问题,同时便于模块化管理代码。包通过目录结构实现物理存储,并通过 package 和 import 关键字在代码中声明和使用。
作用
- 避免命名冲突:不同包中允许存在同名类。
- 访问控制:通过 protected、default(包私有)等修饰符实现包内可见性。
- 模块化组织:将功能相关的类归类到同一包中,如 java.util、java.io。
包的定义与使用
- 声明包
在 Java 文件首行通过 package 关键字声明所属包,包名通常采用逆域名规范(如 com.example.util):
java
package com.example.util;
public class StringUtils { ... }
- 导入包
通过 import 引入其他包的类或静态成员
java
import java.util.List; // 导入单个类
import java.util.*; // 导入包内所有类(不推荐,可能冲突)
import static java.lang.Math.PI; // 导入静态成员
- 包的目录结构
包名与文件系统的目录结构需严格对应
- 包 com.example.util → 文件路径为 ./com/example/util/StringUtils.java
- 编译后的 .class 文件也需放在相同目录下。
JavaDoc
JavaDoc 是 Java 提供的文档生成工具,用于从源代码中的注释生成 HTML 格式的 API 文档。通过标准化注释语法,开发者可以直接在代码中编写文档,并通过工具自动生成可读性强的文档页面。
JavaDoc 注释语法
JavaDoc 注释以 /** 开头,以 */ 结尾,中间包含描述和标签(Tags)。
示例:
java
/**
* 方法的简要描述。
*
* <p>详细描述或其他说明(可跨多行)。</p>
*
* @param 参数名 参数说明
* @return 返回值说明
* @throws 异常类型 异常说明
*/
public int exampleMethod(String param) throws Exception {
// 方法实现
}
常用 JavaDoc 标签
@param:描述方法参数。@return:描述返回值。@throws/@exception:描述可能抛出的异常。@see:添加相关参考链接(类、方法或URL)。@deprecated:标记已过时的代码。@since:说明从哪个版本开始引入。@author:标注作者(通常用于类注释)。@version:标注版本号。
生成 JavaDoc 文档
通过命令行或 IDE 工具生成文档:
命令行方式(示例):
bash
javadoc -d doc_directory -sourcepath src_path -subpackages com.example
-d:指定输出目录。-sourcepath:指定源代码路径。-subpackages:递归处理子包。
IDE 支持:
- IntelliJ IDEA :通过菜单栏的 Tools > Generate JavaDoc 生成。
- Eclipse :右键项目 > Export > JavaDoc。
注释规范建议
-
类注释 :放在类定义前,包含类功能、作者和版本信息。
java/** * 提供用户管理的核心功能。 * * @author John Doe * @version 1.0 */ public class UserManager { ... } -
方法注释:清晰描述方法作用、参数、返回值和异常。
-
字段注释:对公共字段或复杂逻辑字段进行说明。
高级功能
- HTML 标签 :在注释中使用
<p>、<code>等标签增强格式。 {@link}:内联链接到其他类或方法,例如{@link String#equals}。{@code}:以代码字体显示内容,例如{@code int x = 0;}。
注意事项
- 避免冗余注释,仅对公共 API 或关键逻辑添加文档。
- 生成的文档需定期维护,确保与代码同步。
- 可通过
-encoding UTF-8参数指定编码(避免中文乱码)。
Java 控制流程
用户交互Scanner
java.util.Scanner 是 Java 核心类库中用于从不同输入源读取基本数据类型(int/long/float 等)和字符串的工具类,无需手动处理输入流的底层操作,是日常开发、算法题中处理控制台输入的首选,使用前需先导入该类。
导入包
Scanner 位于 java.util 包下,非 java.lang 核心包(该包无需手动导入),因此所有使用 Scanner 的代码,必须在文件顶部添加导入语句
java import java.util.Scanner;
使用流程(3步)
使用 Scanner 处理控制台输入的固定流程,直接复用即可,核心是「创建对象→读取数据→关闭资源」:
-
创建Scanner对象(绑定控制台输入源)
控制台输入的标准源是 System.in,创建对象时将其传入,完成 Scanner 与控制台输入的绑定:
javaScanner sc = new Scanner(System.in); // 核心:绑定System.in,接收控制台输入 -
读取输入数据(按类型选择方法)
Scanner 提供了针对不同基本数据类型的专用读取方法,直接调用即可获取对应类型的输入,无需手动类型转换,常用方法如下:
读取方法 对应数据类型 说明 nextInt() int 读取整数 nextLong() long 读取长整数 nextFloat() float 读取单精度浮点数 nextDouble() double 读取双精度浮点数(常用) next() String 读取非空格分隔的字符串(遇到空格 / 回车停止) nextLine() String 读取整行字符串(包含空格,直到回车停止,最常用) - 关闭Scanner对象(释放资源)
Scanner 绑定了 System.in 输入流,属于需要手动释放的资源,使用完毕后必须调用 close() 方法关闭,否则会造成资源泄漏:
- 关闭Scanner对象(释放资源)
java
sc.close(); // 核心:使用结束后关闭,放在代码最后执行
next()与nextLine()坑点
- next() 方法
核心特点:以有效字符为起点,以空白(空格、Tab、换行等)为分隔符或结束符。
行为逻辑:
会自动跳过输入有效字符前的所有空白,直到读取到第一个有效字符。
读取到有效字符后,遇到下一个空白就停止,不会包含这个空白。
必须读取到有效字符才会结束输入,无法得到带有空格的字符串。
典型场景:适合读取单个不含空格的单词或数据,如用户名、数字等。 nextLine() 方法(常用)
核心特点:以回车键(Enter)为结束符,会读取回车之前的所有字符。
行为逻辑:
可以读取包含空格、Tab 在内的所有字符,直到用户按下回车键。
会将回车键本身作为结束标记,但不会包含在返回的字符串中。
典型场景:适合读取一整行文本,如用户输入的地址、完整句子等。- 常见坑点与解决
在实际开发中,如果先调用 next() 再调用 nextLine(),容易出现 nextLine() 直接读取到空字符串的问题,这是因为 next() 会留下回车键在输入缓冲区中,nextLine() 会直接读取这个回车键并结束。 - 解决方法:
在 next() 之后,额外调用一次 nextLine() 来清空缓冲区中的回车键。
或者全程使用 nextLine(),再对读取的内容进行分割或转换。
Java 的三大基本程序结构
顺序结构
a顺序结构是三大基本程序结构(顺序、选择、循环)中最基础的一种,核心规则是程序代码按照从上到下、从左到右的书写顺序依次执行,无跳转、无分支、无重复,每一行代码执行完毕后,才会执行下一行,流程清晰且唯一,是所有 Java 程序的基础(任何复杂程序的核心片段,底层都是顺序结构的组合)。
特点
- 顺序执行:代码执行顺序与书写顺序完全一致,无任何逻辑判断或循环干预;
- 无分支无重复:不会跳过某段代码,也不会重复执行某段代码;
- 基础结构:选择结构(if/switch)、循环结构(for/while/do-while)都是在顺序结构基础上扩展而来。
选择结构
选择结构是三大基本程序结构(顺序、选择、循环) 之一,核心是根据指定条件的布尔结果(true/false),决定程序的执行分支,会跳过不满足条件的代码块,打破顺序结构的 "单向执行" 特性,是实现程序逻辑判断的核心结构。
Java 提供两种核心选择结构:if 系列选择结构(支持单分支、多分支、嵌套,灵活处理复杂条件)、switch 选择结构(支持多值匹配,代码简洁,适合固定值的分支判断)
equals 比较字符串是否相等
if 选择结构语法
-
单分支 if 结构(满足条件才执行)
javaif (布尔表达式) { // 布尔表达式为 true 时,执行的代码块 } // 表达式为 false 时,直接跳过代码块,执行后续代码 //示范 public class IfDemo { public static void main(String[] args) { int score = 85; // 单分支:分数≥80时,打印表扬信息 if (score >= 80) { System.out.println("成绩优秀,继续加油!"); } System.out.println("程序执行结束"); // 无论条件是否成 立,都会执行 } } -
双分支 if-else 结构(二选一执行)
javaif (布尔表达式) { // 布尔表达式为 true 时,执行的代码块1 } else { // 布尔表达式为 false 时,执行的代码块2 } // 示例 public class IfElseDemo { public static void main(String[] args) { int score = 55; // 双分支:分数≥60及格,否则不及格 if (score >= 60) { System.out.println("成绩及格,顺利通过!"); } else { System.out.println("成绩不及格,需要补考!"); } } } -
多分支 if-else if-else 结构(多选一执行)
有多个互斥执行分支,程序从上到下依次判断布尔表达式,只要有一个条件成立,执行对应代码块后直接跳出整个 if 结构;后续的 else if 分支不再判断,实现 "多选一" 效果;
最后的 else 为默认分支(可选),当所有条件都不成立时执行,若省略 else,所有条件不成立则直接跳过整个结构。javaif (布尔表达式1) { // 表达式1为 true 时,执行代码块1 } else if (布尔表达式2) { // 表达式1为 false、表达式2为 true 时,执行代码块2 } else if (布尔表达式3) { // 表达式1、2为 false、表达式3为 true 时,执行代码块3 } // 可添加任意多个 else if 分支 else { // 所有表达式都为 false 时,执行默认代码块(可选) } //示例 public class IfElseIfDemo { public static void main(String[] args) { int score = 75; String grade; // 多分支:根据分数划分等级 if (score >= 90) { grade = "A(优秀)"; } else if (score >= 80) { grade = "B(良好)"; } else if (score >= 70) { grade = "C(中等)"; } else if (score >= 60) { grade = "D(及格)"; } else { grade = "E(不及格)"; } System.out.println("你的成绩等级为:" + grade); } } -
if 结构的嵌套
在一个 if/else 代码块中,嵌套另一个 if 系列结构,用于处理多层级的条件判断(如 "先判断是否及格,及格后再判断是否优秀")。
java
public class IfNestDemo {
public static void main(String[] args) {
int score = 95;
if (score >= 60) {
System.out.println("成绩及格");
// 嵌套单分支:及格的前提下,判断是否为优秀
if (score >= 90) {
System.out.println("且成绩优秀,获得奖学金!");
}
} else {
System.out.println("成绩不及格,需要补考");
}
}
}
switch 选择结构语法
switch 结构是多值匹配的选择结构,核心是将一个表达式的结果与多个常量值逐一匹配,匹配成功则执行对应分支的代码,适合处理 "固定值判断" 的场景(如按月份判断季节、按数字判断星期),代码比多分支 if-else if 更简洁。
- 基础语法
java
switch (表达式) {
case 常量值1:
// 表达式结果 == 常量值1 时,执行的代码块
break; // 跳出整个 switch 结构(可选,关键)
case 常量值2:
// 表达式结果 == 常量值2 时,执行的代码块
break;
// 可添加任意多个 case 分支
default:
// 表达式结果与所有常量值都不匹配时,执行的默认代码块(可选)
break;
}
注意
- 表达式支持的类型:JDK 7 及以上支持 byte/short/int/char 及其包装类、String 字符串、enum 枚举;不支持 long、double、float 等类型;
- case 常量要求:case 后
必须是常量值(字面量、final 常量),不能是变量、表达式(如 case 1+2 合法,case a 不合法);且多个 case 的常量值不能重复; - break 关键字的作用:执行完某个 case 的代码后,通过 break 跳出整个 switch 结构,避免执行后续 case 代码(即 "穿透现象");
- default 分支:可选,位置可任意(建议放在最后),当所有 case 都不匹配时执行,若省略则直接跳过 switch 结构;
- 穿透现象:如果 case 分支后没有 break,程序会从匹配成功的 case 开始,依次执行后续所有 case 的代码(包括 default),直到遇到 break 或 switch 结束(可利用穿透实现多值共用一个代码块)。
穿透现象的利用(多值共用代码块)
适用于 "多个常量值对应同一逻辑" 的场景,如按月份判断季节(3/4/5 月为春季),无需重复编写代码。
java
public class SwitchPenetrateDemo {
public static void main(String[] args) {
int month = 4;
switch (month) {
case 3:
case 4:
case 5:
System.out.println(month + "月,春季");
break; // 匹配3/4/5任意一个,执行后跳出
case 6:
case 7:
case 8:
System.out.println(month + "月,夏季");
break;
case 9:
case 10:
case 11:
System.out.println(month + "月,秋季");
break;
case 12:
case 1:
case 2:
System.out.println(month + "月,冬季");
break;
default:
System.out.println("无效的月份");
}
}
}
JDK 14 新特性:switch 表达式(简化写法)
JDK 14 引入switch 表达式(可直接赋值给变量),替代传统 switch 语句,自动避免穿透,代码更简洁,支持 -> 语法和 yield 返回值。
java
public class SwitchExpressionDemo {
public static void main(String[] args) {
int month = 10;
// switch 表达式直接赋值给变量,无需break,自动避免穿透
String season = switch (month) {
case 3,4,5 -> "春季"; // 多值用逗号分隔,-> 后跟结果
case 6,7,8 -> "夏季";
case 9,10,11 -> "秋季";
case 12,1,2 -> "冬季";
default -> "无效月份";
};
System.out.println(month + "月," + season);
}
}
选型核心原则
- 用 if:当需要判断范围(如 score >= 90)、多条件组合(如 age > 18 && score >= 60)时,if 结构是唯一选择;
- 用 switch:当需要对固定值做等值匹配(如按星期、月份、枚举值分支)时,优先用 switch,代码更简洁易维护;
- 简单多值匹配(如 3-5 个值):if 和 switch 均可,根据个人习惯选择;
- 大量多值匹配(如 10 个以上):优先用 switch,执行效率略高于 if-else if(JVM 会对 switch 做优化)。
循环结构
循环结构是三大基本程序结构(顺序、选择、循环) 的核心组成,核心作用是根据指定条件,重复执行某一段代码块(循环体),避免重复编写相同逻辑,大幅简化代码、提升开发效率。当条件不满足时,循环终止,程序继续执行后续代码。
Java 提供三种核心循环结构(for/while/do-while),还有增强 for 循环(for-each) 专为遍历集合 / 数组设计,同时支持 break/continue 关键字控制循环流程,以下分模块详细讲解,包含语法、特点、示例及选型建议。
while 循环结构
while 循环是最基础的条件循环,核心逻辑是先判断条件,再执行循环体,适合循环次数不确定的场景(仅知道终止条件,不知道要执行多少次)。
java
// 1. 初始化循环变量(可选,可在外部定义)
初始化语句;
while (布尔条件表达式) {
// 2. 循环体:条件为true时,重复执行的代码
循环体语句;
// 3. 循环变量更新(必须写,否则会造成死循环)
变量更新语句;
}
// 条件为false时,跳出循环,执行后续代码
// 示例:
public class WhileDemo {
public static void main(String[] args) {
int i = 1; // 初始化循环变量:从1开始
int sum = 0; // 初始化总和变量
// 条件:i≤10时,继续循环
while (i <= 10) {
sum += i; // 循环体:累加当前i到sum
i++; // 变量更新:i自增1(关键,避免死循环)
}
System.out.println("1~10的累加和:" + sum); // 循环结束后使用i和sum
System.out.println("循环结束后i的值:" + i);
}
}
注:
- 「先判断,后执行」:如果初始条件直接为 false,循环体一次都不会执行;
- 必须包含「循环变量更新语句」:否则循环条件永远为 true,造成死循环(程序无限执行,无法终止);
- 循环变量通常在外部定义:方便循环结束后继续使用该变量。
do...while 循环结构
do-while 循环是 while 循环的变体,核心逻辑是先执行一次循环体,再判断条件,适合循环体至少需要执行一次的场景(如用户输入验证,必须先让用户输入,再判断是否合法)。
java
// 1. 初始化循环变量
初始化语句;
do {
// 2. 循环体:先执行一次,再判断条件
循环体语句;
// 3. 循环变量更新
变量更新语句;
} while (布尔条件表达式); // 注意:末尾必须加分号
// 示例
import java.util.Scanner;
public class DoWhileDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = 0;
boolean isLegal = false;
// 至少执行一次:先让用户输入,再判断是否合法
do {
System.out.print("请输入一个1~100的整数:");
if (sc.hasNextInt()) { // 判断是否为整数
num = sc.nextInt();
if (num >= 1 && num <= 100) {
isLegal = true; // 输入合法,标记为true
} else {
System.out.println("数字超出范围,请重新输入!");
}
} else {
System.out.println("输入不是整数,请重新输入!");
sc.next(); // 清空无效输入,避免死循环
}
} while (!isLegal); // 输入不合法时,继续循环
System.out.println("输入成功!你输入的数字是:" + num);
sc.close();
}
}
注:
- 「先执行,后判断」:无论初始条件是否为 true,循环体都会执行至少一次(这是与while循环的核心区别);
- 末尾必须加分号:容易遗漏,是常见语法错误;
- 同样需要变量更新语句,避免死循环。
for 循环结构
for 循环是最常用、最规范的循环结构,将「初始化、条件判断、变量更新」三个核心步骤集中在一行,代码简洁、结构清晰,适合循环次数确定的场景(如遍历数组、固定次数的累加 / 遍历)。
- 三要素集中管理:初始化、条件、更新在一行,易读易维护,减少死循环概率;
- 循环变量作用域:若在初始化中定义(如for(int i=0;...)),则仅在循环体内有效,循环结束后无法使用(可避免变量污染);
- 灵活性高:三要素均可省略(但分号不能省),可实现无限循环或适配复杂场景。
java
for (①初始化表达式; ②布尔条件表达式; ④变量更新表达式) {
// ③循环体:条件为true时执行
循环体语句;
}
// 条件为false时,跳出循环,执行后续代码
// 示例
public class ForDemo {
public static void main(String[] args) {
// 初始化:i=1;条件:i≤5;更新:i++
for (int i = 1; i <= 5; i++) {
System.out.println("当前i的值:" + i);
}
// 报错:i在此处未定义(作用域仅在循环内)
// System.out.println(i);
}
}
变体:无限循环(for循环省略三要素)
java
// 分号不能省略,条件表达式省略默认为true,造成无限循环
for (;;) {
System.out.println("无限循环中...");
// 需配合break关键字终止循环,否则程序卡死
if (某条件) {
break;
}
}
增强 for 循环(for-each)
专用于遍历集合 / 数组
增强 for 循环是 JDK 5 引入的简化遍历语法,底层基于迭代器实现,无需关心循环次数和索引,直接遍历集合 / 数组中的每一个元素,适合仅读取元素、不修改元素的遍历场景(如打印数组所有元素、求和)。
java
// 遍历数组
for (元素数据类型 变量名 : 数组名) {
// 变量名 = 数组中当前遍历的元素,直接使用即可
}
// 遍历集合(如ArrayList/LinkedList)
for (元素数据类型 变量名 : 集合名) {
// 变量名 = 集合中当前遍历的元素
}
// 示例
// 遍历数组(求和 + 打印)
public class ForEachArrayDemo {
public static void main(String[] args) {
int[] nums = {10, 20, 30, 40, 50};
int sum = 0;
// 遍历数组:num依次代表数组中的每个元素
for (int num : nums) {
sum += num;
System.out.println("数组元素:" + num);
}
System.out.println("数组元素总和:" + sum);
}
}
// 遍历集合(ArrayList)
import java.util.ArrayList;
import java.util.List;
public class ForEachCollectionDemo {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("张三");
names.add("李四");
names.add("王五");
// 遍历集合:name依次代表集合中的每个字符串
for (String name : names) {
System.out.println("姓名:" + name);
}
}
}
- 无索引、无循环变量:无需手动控制索引,避免索引越界异常(数组遍历的常见错误);
- 只读不可改:遍历的是元素的副本,修改遍历变量不会改变原数组 / 集合的元素;
- 遍历顺序:数组 / 有序集合(如 ArrayList)按正序遍历,无序集合(如 HashSet)按底层存储顺序遍历;
- 适用范围:仅支持实现了 Iterable 接口的对象(数组、Collection 系列集合),不支持 Map(可通过map.keySet()/map.values()间接遍历)。
循环控制关键字 break & continue
Java 提供 break 和 continue 两个关键字,用于灵活控制循环的执行流程,打破 "从头走到尾" 的默认循环规则,适配复杂的循环逻辑(如提前终止循环、跳过某次循环)。
break 关键字:强制终止循环
核心作用
- 执行到 break 时,立即跳出当前所在的循环(for/while/do-while),循环直接结束,后续循环体和变量更新都不再执行;
- 支持嵌套循环:仅跳出最近的一层循环(外层循环继续执行);
- 也可用于 switch 结构(之前选择结构中讲解过)。
java
// 示例:找到 1~10 中第一个能被 3 整除的数,找到后立即终止循环
public class BreakDemo {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i % 3 == 0) {
System.out.println("找到第一个能被3整除的数:" + i);
break; // 立即终止循环,后续i=4~10不再遍历
}
System.out.println("当前遍历:" + i);
}
System.out.println("循环结束");
}
}
continue 关键字:跳过本次循环,继续下一次
核心作用
- 执行到 continue 时,跳过当前次循环的剩余代码,直接执行变量更新语句,然后回到条件判断,继续下一次循环;
- 仅跳过本次,循环不会终止,后续满足条件仍会执行;
- 同样仅作用于最近的一层循环。
java
// 示例:打印 1~10 中的奇数,跳过偶数
public class ContinueDemo {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
continue; // 跳过偶数,直接执行i++,进入下一次循环
}
System.out.println("奇数:" + i); // 仅奇数会执行此行
}
}
}
break & continue 核心区别对比
| 关键字 | 核心作用 | 循环状态 | 后续执行逻辑 |
|---|---|---|---|
| break | 强制终止循环 | 直接结束 | 跳出循环,执行循环外的代码 |
| continue | 跳过本次循环的剩余代码 | 继续执行 | 执行变量更新,回到条件判断 |
嵌套循环:循环中包含循环
嵌套循环是指在一个循环的循环体中,再定义另一个循环,外层循环控制 "行",内层循环控制 "列",适合实现二维结构的遍历 / 打印(如九九乘法表、矩形、三角形)。
外层循环执行一次,内层循环会完整执行所有次数;
支持多层嵌套(但不建议超过 3 层,否则代码可读性极差);
break/continue 仅作用于所在的那一层循环,不会影响外层循环。
java
// 示例
public class NestedForDemo {
public static void main(String[] args) {
// 外层循环:控制行数(1~9行)
for (int i = 1; i <= 9; i++) {
// 内层循环:控制列数(1~当前行数i)
for (int j = 1; j <= i; j++) {
System.out.print(j + "×" + i + "=" + (i*j) + "\t");
}
System.out.println(); // 每行结束后换行
}
}
}
Java 的方法
Java 方法(Method)是将一段完成特定功能的代码块进行封装的语法结构,能实现代码复用、简化逻辑、提升可维护性,是 Java 编程的核心基础之一。简单来说,方法就是一段可被多次调用的 "功能函数",定义一次即可在任意位置重复执行,避免重复编写相同代码。
方法的核心价值:封装逻辑、复用代码、解耦功能、便于调试和维护,一个完整的 Java 程序就是由多个方法(如main方法、自定义方法)组合而成的。
方法的基本概念与结构
Java 方法由方法声明(方法头)和方法体两部分组成,声明定义方法的 "标识和规则",体实现具体功能,语法结构固定且规范:
java
【修饰符】 返回值类型 方法名(【参数列表】) {
// 方法体:完成具体功能的代码块
执行语句;
【return 返回值;】 // 有返回值时必须写,无返回值时可省略return(或仅写return;)
}
设计方法原则:方法本意是功能块,实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,有利于后期的扩展。
| 组成部分 | 说明 |
|---|---|
| 修饰符 | 可选,如 public/private/static/final 等,控制方法的访问权限和特性 |
| 返回值类型 | 方法执行后返回的数据类型:无返回值用 void;有返回值需指定具体类型(如 int/String) |
| 方法名 | 符合标识符命名规范,小驼峰式(如 addNum),见名知意 |
| 参数列表 | 可选,格式:数据类型 参数名[, 数据类型 参数名...],是方法接收的输入数据 |
| 方法体 | 方法的核心逻辑代码块 |
| return | 可选:无返回值(void):可省略 return,或写 return; 终止方法;有返回值:必须通过 return 返回对应类型的值 |
方法的调用
Java都是值传递
| 概念 | 说明 |
|---|---|
| 静态方法 | 用 static 修饰,属于「类」本身,不依赖对象即可调用(如 main 方法) |
| 实例方法 | 无 static 修饰,属于「对象」,必须创建对象后才能调用 |
| 形参 | 方法定义时的参数(如 add(int a) 中的 a),是 "输入占位符" |
| 实参 | 方法调用时传入的具体值(如 add(5) 中的 5),需与形参匹配 |
静态方法调用
-
同类中调用直接使用
[ 方法名(实参)]java// 示例 package com.day1; public class StaticMethodDemo { // 定义静态方法:加法 public static int add(int a, int b) { return a + b; } // 主方法(静态):程序入口 public static void main(String[] args) { // 同类中调用静态方法:直接调用 int result = add(10, 20); System.out.println(result); // 输出 30 } } -
不同类中调用静态方法
格式:
类名.方法名(实参)(需保证方法访问权限为 public/protected 或同包默认)。java// 步骤 1:定义被调用的类(含静态方法) // 包名:com.utils package com.utils; public class MathUtil { // 公共静态方法:计算两数乘积 public static int multiply(int a, int b) { return a * b; } } // 步骤 2:在另一个类中调用 // 包名:com.day1(与MathUtil不同包) package com.day1; // 导入目标类(不同包必须导入,同包可省略) import com.utils.MathUtil; public class TestCall { public static void main(String[] args) { // 不同类调用静态方法:类名.方法名 int product = MathUtil.multiply(5, 6); System.out.println(product); // 输出 30 } }
实例方法调用
实例方法依赖对象存在,必须先创建对象,再通过「对象。方法名」调用。
- 同类中调用实例方法
java
package com.day1;
public class InstanceMethodDemo {
// 定义实例方法:无static修饰
public String sayHello(String name) {
return "你好," + name + "!";
}
public static void main(String[] args) {
// 步骤1:创建当前类的对象(关键字new)
InstanceMethodDemo demo = new InstanceMethodDemo();
// 步骤2:通过对象调用实例方法
String hello = demo.sayHello("Java");
System.out.println(hello); // 输出:你好,Java!
}
}
方法的重载(Overload)
方法重载是 Java 中实现 "同名不同逻辑" 的核心特性,也是面向对象编程中多态的基础体现之一。以下从定义、规则、示例、应用场景到避坑点,全方位讲解方法重载。
- 核心价值:简化同名功能的方法调用(比如 add 方法既可以加 int,也可以加 double,不用命名为 addInt/addDouble);
- 关键误区:方法重载与返回值类型、修饰符无关,
仅看「参数列表」。
|须满足的核心条件(缺一不可)
| 条件 | 说明 |
|---|---|
| 同一类中 | 重载方法必须在同一个类内(子类与父类的同名方法是重写,不是重载) |
| 方法名完全相同 | 比如都叫 add、都叫 print |
| 参数列表必须不同 | 满足以下任一即可:① 参数个数不同(如 add(int a) vs add(int a, int b));② 参数类型不同(如 add(int a) vs add(double a));③ 参数顺序不同(如 add(int a, double b) vs add(double a, int b))。 |
java
// 示例
// 参数个数不同的重载
public class OverloadDemo1 {
// 重载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;
}
public static void main(String[] args) {
System.out.println(add(1, 2)); // 调用重载1,输出3
System.out.println(add(1, 2, 3)); // 调用重载2,输出6
}
}
// 参数类型不同的重载
public class OverloadDemo2 {
// 重载1:int类型加法
public static int add(int a, int b) {
return a + b;
}
// 重载2:double类型加法(参数类型不同)
public static double add(double a, double b) {
return a + b;
}
public static void main(String[] args) {
System.out.println(add(1, 2)); // 调用重载1,输出3
System.out.println(add(1.5, 2.5)); // 调用重载2,输出4.0
}
}
// 参数顺序不同的重载(极少用,但合法)
public class OverloadDemo3 {
// 重载1:int在前,double在后
public static double calculate(int a, double b) {
return a + b;
}
// 重载2:double在前,int在后(参数顺序不同)
public static double calculate(double a, int b) {
return a * b;
}
public static void main(String[] args) {
System.out.println(calculate(2, 3.0)); // 调用重载1,输出5.0
System.out.println(calculate(2.0, 3)); // 调用重载2,输出6.0
}
}
可变参数
可变参数(Variable Arguments,简称 Varargs)是 JDK 5 引入的特性,允许方法接收任意个数的同类型参数,本质是编译器自动将可变参数封装为数组,简化了多参数方法的定义和调用。
语法:
java
[修饰符] 返回值类型 方法名(数据类型... 参数名) {
// 方法体(参数名可当作数组使用)
}
关键标识:...(三个点)必须紧跟在数据类型后,参数名前;
可变参数必须是方法的最后一个参数(避免参数匹配歧义);
一个方法只能有一个可变参数。
// 示例
public class VarargsDemo {
// 可变参数方法:计算多个int的和
public static int sum(int... nums) {
int total = 0;
// 可变参数可当作数组遍历
for (int num : nums) {
total += num;
}
return total;
}
public static void main(String[] args) {
// 调用:可传0个、1个、多个参数
System.out.println(sum()); // 0(无参数)
System.out.println(sum(1)); // 1(1个参数)
System.out.println(sum(1, 2, 3)); // 6(多个参数)
// 也可直接传数组(编译器自动兼容)
int[] arr = {4, 5, 6};
System.out.println(sum(arr)); // 15
}
}
递归
递归是编程中一种重要的算法思想,指方法自身调用自身,通过将复杂问题拆解为规模更小的同类子问题,最终通过终止条件结束递归并回溯结果。Java 中递归广泛应用于分治算法(如快速排序、归并排序)、树形结构遍历(如二叉树)等场景。
递归的核心要素
|递归必须满足| 两个核心条件,否则会导致栈溢出(StackOverflowError):
| 要素 | 说明 |
|---|---|
| 递归终止条件 | 定义 "最小子问题" 的解,当满足条件时停止递归,返回基础值(避免无限递归) |
| 递归递推关系 | 将原问题拆解为规模更小的子问题,调用自身解决子问题,并逐步向终止条件靠近 |
java
[修饰符] 返回值类型 方法名(参数) {
// 1. 递归终止条件(必须有)
if (终止条件) {
return 基础值;
}
// 2. 递推:拆解问题,调用自身
return 方法名(更小的参数) + 逻辑处理;
}
//二、递归的基础示例
示例 1:计算阶乘(最经典)
阶乘定义:n! = n × (n-1) × (n-2) × ... × 1,且 0! = 1、1! = 1
public class FactorialDemo {
// 递归计算阶乘
public static int factorial(int n) {
// 终止条件:n≤1时返回1
if (n <= 1) {
return 1;
}
// 递推:n! = n × (n-1)!
return n * factorial(n - 1);
}
public static void main(String[] args) {
System.out.println(factorial(5)); // 输出:120(5×4×3×2×1)
System.out.println(factorial(0)); // 输出:1(符合定义)
}
}
// 过程拆解
factorial(5) → 5 × factorial(4)
factorial(4) → 4 × factorial(3)
factorial(3) → 3 × factorial(2)
factorial(2) → 2 × factorial(1)
factorial(1) → 1(终止条件)
回溯计算:2×1=2 → 3×2=6 → 4×6=24 → 5×24=120
·