一、变量概述
1.1 什么是变量
在程序运行过程中,数据需要被存储、读取和修改。变量(Variable)就是程序中用于存储数据的一块命名内存空间。可以把变量理解为一个"带标签的容器"——标签是变量名,容器里存放的是具体的数值。当程序需要使用这个数值时,通过变量名即可访问;当需要改变这个数值时,也通过变量名进行赋值。
用生活中的例子来类比:一个停车场有若干个车位,每个车位有一个编号(如A12、B07)。当你把车停进去后,别人可以通过车位编号找到你的车。这里的"车位编号"相当于变量名,"车位"相当于内存空间,"车"相当于变量中存储的值。
#mermaid-svg-Nr7YHMXGQ83wid9m{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Nr7YHMXGQ83wid9m .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Nr7YHMXGQ83wid9m .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Nr7YHMXGQ83wid9m .error-icon{fill:#552222;}#mermaid-svg-Nr7YHMXGQ83wid9m .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Nr7YHMXGQ83wid9m .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Nr7YHMXGQ83wid9m .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Nr7YHMXGQ83wid9m .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Nr7YHMXGQ83wid9m .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Nr7YHMXGQ83wid9m .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Nr7YHMXGQ83wid9m .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Nr7YHMXGQ83wid9m .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Nr7YHMXGQ83wid9m .marker.cross{stroke:#333333;}#mermaid-svg-Nr7YHMXGQ83wid9m svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Nr7YHMXGQ83wid9m p{margin:0;}#mermaid-svg-Nr7YHMXGQ83wid9m .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-Nr7YHMXGQ83wid9m .cluster-label text{fill:#333;}#mermaid-svg-Nr7YHMXGQ83wid9m .cluster-label span{color:#333;}#mermaid-svg-Nr7YHMXGQ83wid9m .cluster-label span p{background-color:transparent;}#mermaid-svg-Nr7YHMXGQ83wid9m .label text,#mermaid-svg-Nr7YHMXGQ83wid9m span{fill:#333;color:#333;}#mermaid-svg-Nr7YHMXGQ83wid9m .node rect,#mermaid-svg-Nr7YHMXGQ83wid9m .node circle,#mermaid-svg-Nr7YHMXGQ83wid9m .node ellipse,#mermaid-svg-Nr7YHMXGQ83wid9m .node polygon,#mermaid-svg-Nr7YHMXGQ83wid9m .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Nr7YHMXGQ83wid9m .rough-node .label text,#mermaid-svg-Nr7YHMXGQ83wid9m .node .label text,#mermaid-svg-Nr7YHMXGQ83wid9m .image-shape .label,#mermaid-svg-Nr7YHMXGQ83wid9m .icon-shape .label{text-anchor:middle;}#mermaid-svg-Nr7YHMXGQ83wid9m .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Nr7YHMXGQ83wid9m .rough-node .label,#mermaid-svg-Nr7YHMXGQ83wid9m .node .label,#mermaid-svg-Nr7YHMXGQ83wid9m .image-shape .label,#mermaid-svg-Nr7YHMXGQ83wid9m .icon-shape .label{text-align:center;}#mermaid-svg-Nr7YHMXGQ83wid9m .node.clickable{cursor:pointer;}#mermaid-svg-Nr7YHMXGQ83wid9m .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Nr7YHMXGQ83wid9m .arrowheadPath{fill:#333333;}#mermaid-svg-Nr7YHMXGQ83wid9m .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Nr7YHMXGQ83wid9m .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Nr7YHMXGQ83wid9m .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Nr7YHMXGQ83wid9m .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Nr7YHMXGQ83wid9m .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Nr7YHMXGQ83wid9m .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Nr7YHMXGQ83wid9m .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Nr7YHMXGQ83wid9m .cluster text{fill:#333;}#mermaid-svg-Nr7YHMXGQ83wid9m .cluster span{color:#333;}#mermaid-svg-Nr7YHMXGQ83wid9m div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Nr7YHMXGQ83wid9m .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Nr7YHMXGQ83wid9m rect.text{fill:none;stroke-width:0;}#mermaid-svg-Nr7YHMXGQ83wid9m .icon-shape,#mermaid-svg-Nr7YHMXGQ83wid9m .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Nr7YHMXGQ83wid9m .icon-shape p,#mermaid-svg-Nr7YHMXGQ83wid9m .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Nr7YHMXGQ83wid9m .icon-shape .label rect,#mermaid-svg-Nr7YHMXGQ83wid9m .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Nr7YHMXGQ83wid9m .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Nr7YHMXGQ83wid9m .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Nr7YHMXGQ83wid9m :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
变量名
内存地址
存储的值
在Java中,每个变量都有三个核心属性:
| 数据类型 | 决定变量能存储什么类型的值,以及占用多少内存 | int、double、String |
| 变量名 | 程序中引用该变量的标识符 | age、studentName |
| 值 | 实际存储的数据 | 25、"张三" |
1.2 变量的本质:内存模型
从底层角度来看,声明一个变量的过程实际上是向JVM申请一块内存空间。以int age = 25;为例:
内存空间Java虚拟机Java程序内存空间Java虚拟机Java程序#mermaid-svg-2faWJWAHC7DcVKcV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2faWJWAHC7DcVKcV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2faWJWAHC7DcVKcV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2faWJWAHC7DcVKcV .error-icon{fill:#552222;}#mermaid-svg-2faWJWAHC7DcVKcV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2faWJWAHC7DcVKcV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2faWJWAHC7DcVKcV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2faWJWAHC7DcVKcV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2faWJWAHC7DcVKcV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2faWJWAHC7DcVKcV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2faWJWAHC7DcVKcV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2faWJWAHC7DcVKcV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2faWJWAHC7DcVKcV .marker.cross{stroke:#333333;}#mermaid-svg-2faWJWAHC7DcVKcV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2faWJWAHC7DcVKcV p{margin:0;}#mermaid-svg-2faWJWAHC7DcVKcV .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-2faWJWAHC7DcVKcV text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-2faWJWAHC7DcVKcV .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-2faWJWAHC7DcVKcV .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-2faWJWAHC7DcVKcV .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-2faWJWAHC7DcVKcV .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-2faWJWAHC7DcVKcV #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-2faWJWAHC7DcVKcV .sequenceNumber{fill:white;}#mermaid-svg-2faWJWAHC7DcVKcV #sequencenumber{fill:#333;}#mermaid-svg-2faWJWAHC7DcVKcV #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-2faWJWAHC7DcVKcV .messageText{fill:#333;stroke:none;}#mermaid-svg-2faWJWAHC7DcVKcV .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-2faWJWAHC7DcVKcV .labelText,#mermaid-svg-2faWJWAHC7DcVKcV .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-2faWJWAHC7DcVKcV .loopText,#mermaid-svg-2faWJWAHC7DcVKcV .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-2faWJWAHC7DcVKcV .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-2faWJWAHC7DcVKcV .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-2faWJWAHC7DcVKcV .noteText,#mermaid-svg-2faWJWAHC7DcVKcV .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-2faWJWAHC7DcVKcV .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-2faWJWAHC7DcVKcV .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-2faWJWAHC7DcVKcV .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-2faWJWAHC7DcVKcV .actorPopupMenu{position:absolute;}#mermaid-svg-2faWJWAHC7DcVKcV .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-2faWJWAHC7DcVKcV .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-2faWJWAHC7DcVKcV .actor-man circle,#mermaid-svg-2faWJWAHC7DcVKcV line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-2faWJWAHC7DcVKcV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}int age = 25分配4字节空间(地址0x1000)写入值25(0x00000019)绑定 age ->> 0x1000
理解变量的内存模型有助于理解后续的作用域、生命周期和垃圾回收等概念。
二、变量的声明与初始化
2.1 声明语法
Java是强类型语言,每个变量在使用前必须先声明其类型。声明变量的基本语法为:
数据类型 变量名;
也可以在声明的同时赋予初始值:
数据类型 变量名 = 初始值;
以下是各种数据类型的变量声明示例:
// 基本类型变量
int count = 100;
double price = 29.99;
boolean isActive = true;
char grade = 'A';
long timestamp = 1692000000000L;
float pi = 3.14f;
// 引用类型变量
String name = "张三";
int[] scores = {85, 90, 78, 92};
List<String> names = new ArrayList<>();
2.2 多变量声明
Java允许在一行中声明多个同类型变量:
// 一行声明多个变量
int a, b, c;
// 声明并分别初始化
int x = 1, y = 2, z = 3;
// 部分初始化(不推荐)
int m = 10, n, p = 20; // n未初始化
虽然语法上允许,但从代码可读性考虑,建议每行只声明一个变量:
// 推荐写法
int x = 1;
int y = 2;
int z = 3;
2.3 声明与赋值的分离
变量的声明和赋值可以分两步进行:
// 第一步:声明
String message;
// 第二步:赋值(必须在首次使用之前)
message = "Hello, Java!";
System.out.println(message); // 输出:Hello, Java!
需要注意的是,局部变量在赋值之前不能使用,否则编译器会报错:
int result;
System.out.println(result); // 编译错误:variable result might not have been initialized
三、变量命名规范
3.1 Java标识符规则
变量名属于Java标识符(Identifier),必须遵循以下规则:
| 首字符 | 字母、下划线_或美元符号$ | name、_value、$price | 1name、@count |
| 后续字符 | 字母、数字、下划线、美元符号 | age2、first_name | name@、user id |
| 大小写敏感 | age和Age是不同的变量 | age = 10; Age = 20 | – |
| 不能使用关键字 | 不能用int、class等保留字 | – | int class = 1; |
| 不能使用保留字 | goto、const等 | – | int goto = 2; |
3.2 驼峰命名法(Camel Case)
Java社区广泛采用驼峰命名法,具体规则如下:
// 小驼峰命名法(lowerCamelCase)—— 用于变量名和方法名
String studentName; // 正确
int totalScore; // 正确
boolean isGraduated; // 正确
// 错误示范
String student_name; // 不符合Java惯例(虽然语法合法)
String StudentName; // 与类名混淆,不推荐
// 大驼峰命名法(UpperCamelCase)—— 用于类名和接口名
class StudentManager {}
interface DataProcessor {}
3.3 命名的艺术:见名知意
一个好的变量名应该能够清晰传达其用途和含义,让代码像自然语言一样易读:
// ❌ 不好的命名——含义模糊
int d; // d是什么?天数?距离?
String s; // s是什么?学生?字符串?
boolean f; // f是什么?标志?找到了?
// ✅ 好的命名——见名知意
int daysSinceRegistration; // 一目了然:注册以来的天数
String studentFullName; // 清晰表达:学生全名
boolean hasPermission; // 语义明确:是否拥有权限
好的命名遵循以下原则:
- 使用完整的单词,避免无意义的缩写(address而非addr)
- 布尔变量以is、has、can、should开头
- 集合类变量使用复数形式(students、orderItems)
- 避免使用拼音,使用准确的英文词汇
- 避免单字母变量,除非是循环中的临时变量(i、j、k)
四、变量的分类
Java中的变量根据声明位置和修饰符的不同,可以分为三大类:局部变量、实例变量(成员变量)和静态变量(类变量)。
4.1 分类对比总览
#mermaid-svg-9YjYA660CqQLr7vE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9YjYA660CqQLr7vE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9YjYA660CqQLr7vE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9YjYA660CqQLr7vE .error-icon{fill:#552222;}#mermaid-svg-9YjYA660CqQLr7vE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9YjYA660CqQLr7vE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9YjYA660CqQLr7vE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9YjYA660CqQLr7vE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9YjYA660CqQLr7vE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9YjYA660CqQLr7vE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9YjYA660CqQLr7vE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9YjYA660CqQLr7vE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9YjYA660CqQLr7vE .marker.cross{stroke:#333333;}#mermaid-svg-9YjYA660CqQLr7vE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9YjYA660CqQLr7vE p{margin:0;}#mermaid-svg-9YjYA660CqQLr7vE .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-9YjYA660CqQLr7vE .cluster-label text{fill:#333;}#mermaid-svg-9YjYA660CqQLr7vE .cluster-label span{color:#333;}#mermaid-svg-9YjYA660CqQLr7vE .cluster-label span p{background-color:transparent;}#mermaid-svg-9YjYA660CqQLr7vE .label text,#mermaid-svg-9YjYA660CqQLr7vE span{fill:#333;color:#333;}#mermaid-svg-9YjYA660CqQLr7vE .node rect,#mermaid-svg-9YjYA660CqQLr7vE .node circle,#mermaid-svg-9YjYA660CqQLr7vE .node ellipse,#mermaid-svg-9YjYA660CqQLr7vE .node polygon,#mermaid-svg-9YjYA660CqQLr7vE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9YjYA660CqQLr7vE .rough-node .label text,#mermaid-svg-9YjYA660CqQLr7vE .node .label text,#mermaid-svg-9YjYA660CqQLr7vE .image-shape .label,#mermaid-svg-9YjYA660CqQLr7vE .icon-shape .label{text-anchor:middle;}#mermaid-svg-9YjYA660CqQLr7vE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9YjYA660CqQLr7vE .rough-node .label,#mermaid-svg-9YjYA660CqQLr7vE .node .label,#mermaid-svg-9YjYA660CqQLr7vE .image-shape .label,#mermaid-svg-9YjYA660CqQLr7vE .icon-shape .label{text-align:center;}#mermaid-svg-9YjYA660CqQLr7vE .node.clickable{cursor:pointer;}#mermaid-svg-9YjYA660CqQLr7vE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9YjYA660CqQLr7vE .arrowheadPath{fill:#333333;}#mermaid-svg-9YjYA660CqQLr7vE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9YjYA660CqQLr7vE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9YjYA660CqQLr7vE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9YjYA660CqQLr7vE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9YjYA660CqQLr7vE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9YjYA660CqQLr7vE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9YjYA660CqQLr7vE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9YjYA660CqQLr7vE .cluster text{fill:#333;}#mermaid-svg-9YjYA660CqQLr7vE .cluster span{color:#333;}#mermaid-svg-9YjYA660CqQLr7vE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9YjYA660CqQLr7vE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9YjYA660CqQLr7vE rect.text{fill:none;stroke-width:0;}#mermaid-svg-9YjYA660CqQLr7vE .icon-shape,#mermaid-svg-9YjYA660CqQLr7vE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9YjYA660CqQLr7vE .icon-shape p,#mermaid-svg-9YjYA660CqQLr7vE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9YjYA660CqQLr7vE .icon-shape .label rect,#mermaid-svg-9YjYA660CqQLr7vE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9YjYA660CqQLr7vE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9YjYA660CqQLr7vE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9YjYA660CqQLr7vE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
Java变量
按声明位置分类
局部变量 local variable
成员变量 member variable
实例变量 instance variable
静态变量 static variable / 类变量 class variable
方法内部声明
代码块内部声明
方法参数
类中声明 无static修饰
类中声明 有static修饰
4.2 局部变量(Local Variables)
局部变量是在方法、构造器或代码块内部声明的变量。它们只在声明它们的代码块内有效,出了代码块就无法访问。
public class LocalVariableDemo {
public void calculateSum() {
// a和b是局部变量——在方法内部声明
int a = 10;
int b = 20;
int sum = a + b; // sum也是局部变量
System.out.println("和:" + sum);
}
public void printNumbers() {
// 代码块内的局部变量
for (int i = 0; i < 5; i++) { // i是循环局部变量
System.out.println(i);
}
// System.out.println(i); // 编译错误:i在此处不可见
}
public void greet(String name) { // name是方法参数,也属于局部变量
String greeting = "你好," + name;
System.out.println(greeting);
}
}
局部变量的特点:
| 存储位置 | 栈内存(Stack) |
| 默认值 | 没有默认值,必须手动初始化后才能使用 |
| 生命周期 | 从声明处开始,到所在代码块结束 |
| 访问修饰符 | 不能使用public/private/protected等修饰符 |
| 线程安全 | 每个线程拥有独立的栈帧,天然线程安全 |
4.3 实例变量(Instance Variables / 成员变量)
实例变量是在类内部、方法外部声明的、没有static修饰的变量。每个类的实例(对象)都有自己的一份实例变量副本。
public class Student {
// 实例变量——属于每个Student对象
private String name;
private int age;
private String studentId;
public Student(String name, int age, String studentId) {
this.name = name;
this.age = age;
this.studentId = studentId;
}
public void display() {
System.out.println(name + "," + age + "岁,学号:" + studentId);
}
public static void main(String[] args) {
Student s1 = new Student("张三", 20, "2024001");
Student s2 = new Student("李四", 21, "2024002");
s1.display(); // 张三,20岁,学号:2024001
s2.display(); // 李四,21岁,学号:2024002
// s1和s2拥有各自独立的name、age、studentId副本
}
}
#mermaid-svg-05LW9fJboUBFYGuC{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-05LW9fJboUBFYGuC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-05LW9fJboUBFYGuC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-05LW9fJboUBFYGuC .error-icon{fill:#552222;}#mermaid-svg-05LW9fJboUBFYGuC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-05LW9fJboUBFYGuC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-05LW9fJboUBFYGuC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-05LW9fJboUBFYGuC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-05LW9fJboUBFYGuC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-05LW9fJboUBFYGuC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-05LW9fJboUBFYGuC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-05LW9fJboUBFYGuC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-05LW9fJboUBFYGuC .marker.cross{stroke:#333333;}#mermaid-svg-05LW9fJboUBFYGuC svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-05LW9fJboUBFYGuC p{margin:0;}#mermaid-svg-05LW9fJboUBFYGuC .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-05LW9fJboUBFYGuC .cluster-label text{fill:#333;}#mermaid-svg-05LW9fJboUBFYGuC .cluster-label span{color:#333;}#mermaid-svg-05LW9fJboUBFYGuC .cluster-label span p{background-color:transparent;}#mermaid-svg-05LW9fJboUBFYGuC .label text,#mermaid-svg-05LW9fJboUBFYGuC span{fill:#333;color:#333;}#mermaid-svg-05LW9fJboUBFYGuC .node rect,#mermaid-svg-05LW9fJboUBFYGuC .node circle,#mermaid-svg-05LW9fJboUBFYGuC .node ellipse,#mermaid-svg-05LW9fJboUBFYGuC .node polygon,#mermaid-svg-05LW9fJboUBFYGuC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-05LW9fJboUBFYGuC .rough-node .label text,#mermaid-svg-05LW9fJboUBFYGuC .node .label text,#mermaid-svg-05LW9fJboUBFYGuC .image-shape .label,#mermaid-svg-05LW9fJboUBFYGuC .icon-shape .label{text-anchor:middle;}#mermaid-svg-05LW9fJboUBFYGuC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-05LW9fJboUBFYGuC .rough-node .label,#mermaid-svg-05LW9fJboUBFYGuC .node .label,#mermaid-svg-05LW9fJboUBFYGuC .image-shape .label,#mermaid-svg-05LW9fJboUBFYGuC .icon-shape .label{text-align:center;}#mermaid-svg-05LW9fJboUBFYGuC .node.clickable{cursor:pointer;}#mermaid-svg-05LW9fJboUBFYGuC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-05LW9fJboUBFYGuC .arrowheadPath{fill:#333333;}#mermaid-svg-05LW9fJboUBFYGuC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-05LW9fJboUBFYGuC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-05LW9fJboUBFYGuC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-05LW9fJboUBFYGuC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-05LW9fJboUBFYGuC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-05LW9fJboUBFYGuC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-05LW9fJboUBFYGuC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-05LW9fJboUBFYGuC .cluster text{fill:#333;}#mermaid-svg-05LW9fJboUBFYGuC .cluster span{color:#333;}#mermaid-svg-05LW9fJboUBFYGuC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-05LW9fJboUBFYGuC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-05LW9fJboUBFYGuC rect.text{fill:none;stroke-width:0;}#mermaid-svg-05LW9fJboUBFYGuC .icon-shape,#mermaid-svg-05LW9fJboUBFYGuC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-05LW9fJboUBFYGuC .icon-shape p,#mermaid-svg-05LW9fJboUBFYGuC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-05LW9fJboUBFYGuC .icon-shape .label rect,#mermaid-svg-05LW9fJboUBFYGuC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-05LW9fJboUBFYGuC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-05LW9fJboUBFYGuC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-05LW9fJboUBFYGuC :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
栈内存
堆内存
Student对象 s1
name = 张三
age = 20
studentId = 2024001
Student对象 s2
name = 李四
age = 21
studentId = 2024002
s1 引用
s2 引用
实例变量的特点:
| 存储位置 | 堆内存(Heap),随对象分配 |
| 默认值 | 有默认值(int为0,boolean为false,引用类型为null) |
| 生命周期 | 随对象的创建而创建,随对象的销毁而销毁 |
| 访问修饰符 | 可以使用public/protected/private/默认 |
| 访问方式 | 通过对象引用.变量名访问 |
4.4 静态变量(Static Variables / 类变量)
静态变量是用static关键字修饰的、在类内部声明的变量。它与类绑定而非与对象绑定——整个类只有一份静态变量的副本,被所有实例共享。
public class Counter {
// 实例变量——每个对象独立
private int instanceCount = 0;
// 静态变量——所有对象共享
private static int totalCount = 0;
public Counter() {
instanceCount++;
totalCount++;
}
public void display() {
System.out.println("实例计数:" + instanceCount);
System.out.println("总计计数:" + totalCount);
}
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
Counter c3 = new Counter();
c1.display(); // 实例计数:1,总计计数:3
c2.display(); // 实例计数:1,总计计数:3
c3.display(); // 实例计数:1,总计计数:3
// 注意:每个对象的instanceCount都是1(独立),
// 而totalCount是3(共享)
}
}
#mermaid-svg-lmLWssxbIoaDZT6i{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lmLWssxbIoaDZT6i .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lmLWssxbIoaDZT6i .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lmLWssxbIoaDZT6i .error-icon{fill:#552222;}#mermaid-svg-lmLWssxbIoaDZT6i .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lmLWssxbIoaDZT6i .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lmLWssxbIoaDZT6i .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lmLWssxbIoaDZT6i .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lmLWssxbIoaDZT6i .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lmLWssxbIoaDZT6i .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lmLWssxbIoaDZT6i .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lmLWssxbIoaDZT6i .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lmLWssxbIoaDZT6i .marker.cross{stroke:#333333;}#mermaid-svg-lmLWssxbIoaDZT6i svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lmLWssxbIoaDZT6i p{margin:0;}#mermaid-svg-lmLWssxbIoaDZT6i .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-lmLWssxbIoaDZT6i .cluster-label text{fill:#333;}#mermaid-svg-lmLWssxbIoaDZT6i .cluster-label span{color:#333;}#mermaid-svg-lmLWssxbIoaDZT6i .cluster-label span p{background-color:transparent;}#mermaid-svg-lmLWssxbIoaDZT6i .label text,#mermaid-svg-lmLWssxbIoaDZT6i span{fill:#333;color:#333;}#mermaid-svg-lmLWssxbIoaDZT6i .node rect,#mermaid-svg-lmLWssxbIoaDZT6i .node circle,#mermaid-svg-lmLWssxbIoaDZT6i .node ellipse,#mermaid-svg-lmLWssxbIoaDZT6i .node polygon,#mermaid-svg-lmLWssxbIoaDZT6i .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lmLWssxbIoaDZT6i .rough-node .label text,#mermaid-svg-lmLWssxbIoaDZT6i .node .label text,#mermaid-svg-lmLWssxbIoaDZT6i .image-shape .label,#mermaid-svg-lmLWssxbIoaDZT6i .icon-shape .label{text-anchor:middle;}#mermaid-svg-lmLWssxbIoaDZT6i .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-lmLWssxbIoaDZT6i .rough-node .label,#mermaid-svg-lmLWssxbIoaDZT6i .node .label,#mermaid-svg-lmLWssxbIoaDZT6i .image-shape .label,#mermaid-svg-lmLWssxbIoaDZT6i .icon-shape .label{text-align:center;}#mermaid-svg-lmLWssxbIoaDZT6i .node.clickable{cursor:pointer;}#mermaid-svg-lmLWssxbIoaDZT6i .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-lmLWssxbIoaDZT6i .arrowheadPath{fill:#333333;}#mermaid-svg-lmLWssxbIoaDZT6i .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lmLWssxbIoaDZT6i .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lmLWssxbIoaDZT6i .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lmLWssxbIoaDZT6i .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lmLWssxbIoaDZT6i .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lmLWssxbIoaDZT6i .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-lmLWssxbIoaDZT6i .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lmLWssxbIoaDZT6i .cluster text{fill:#333;}#mermaid-svg-lmLWssxbIoaDZT6i .cluster span{color:#333;}#mermaid-svg-lmLWssxbIoaDZT6i div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lmLWssxbIoaDZT6i .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lmLWssxbIoaDZT6i rect.text{fill:none;stroke-width:0;}#mermaid-svg-lmLWssxbIoaDZT6i .icon-shape,#mermaid-svg-lmLWssxbIoaDZT6i .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lmLWssxbIoaDZT6i .icon-shape p,#mermaid-svg-lmLWssxbIoaDZT6i .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-lmLWssxbIoaDZT6i .icon-shape .label rect,#mermaid-svg-lmLWssxbIoaDZT6i .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lmLWssxbIoaDZT6i .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-lmLWssxbIoaDZT6i .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-lmLWssxbIoaDZT6i :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
堆内存
方法区/元空间
静态变量 totalCount = 3
Counter对象 c1
instanceCount = 1
Counter对象 c2
instanceCount = 1
Counter对象 c3
instanceCount = 1
静态变量的特点:
| 存储位置 | 方法区(Method Area)/ 元空间(Metaspace,JDK 8+) |
| 默认值 | 有默认值(与实例变量相同) |
| 生命周期 | 类加载时创建,类卸载时销毁 |
| 访问方式 | 类名.变量名(推荐)或对象引用.变量名(不推荐) |
| 共享性 | 所有实例共享同一个值 |
4.5 三种变量的全面对比
| 声明位置 | 方法/代码块内 | 类内、方法外、无static | 类内、方法外、有static |
| 存储位置 | 栈内存 | 堆内存 | 方法区/元空间 |
| 默认值 | 无,必须初始化 | 有 | 有 |
| 生命周期 | 代码块执行期间 | 与对象相同 | 与类相同 |
| 访问修饰符 | 不能使用 | 可以使用 | 可以使用 |
| 归属 | 方法/代码块 | 对象实例 | 类本身 |
| 线程安全 | 天然安全 | 不安全 | 不安全(需同步) |
| 访问方式 | 直接使用 | 对象.变量名 | 类名.变量名 |
五、变量的作用域
5.1 作用域的概念
作用域(Scope)是指变量在程序中有效的范围。在Java中,变量的作用域由**声明它的花括号{}**决定——变量从声明的位置开始,到包含它的代码块结束为止都是有效的。
#mermaid-svg-t61Z3C7qnWKeR3iv{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-t61Z3C7qnWKeR3iv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-t61Z3C7qnWKeR3iv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-t61Z3C7qnWKeR3iv .error-icon{fill:#552222;}#mermaid-svg-t61Z3C7qnWKeR3iv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-t61Z3C7qnWKeR3iv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-t61Z3C7qnWKeR3iv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-t61Z3C7qnWKeR3iv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-t61Z3C7qnWKeR3iv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-t61Z3C7qnWKeR3iv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-t61Z3C7qnWKeR3iv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-t61Z3C7qnWKeR3iv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-t61Z3C7qnWKeR3iv .marker.cross{stroke:#333333;}#mermaid-svg-t61Z3C7qnWKeR3iv svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-t61Z3C7qnWKeR3iv p{margin:0;}#mermaid-svg-t61Z3C7qnWKeR3iv .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-t61Z3C7qnWKeR3iv .cluster-label text{fill:#333;}#mermaid-svg-t61Z3C7qnWKeR3iv .cluster-label span{color:#333;}#mermaid-svg-t61Z3C7qnWKeR3iv .cluster-label span p{background-color:transparent;}#mermaid-svg-t61Z3C7qnWKeR3iv .label text,#mermaid-svg-t61Z3C7qnWKeR3iv span{fill:#333;color:#333;}#mermaid-svg-t61Z3C7qnWKeR3iv .node rect,#mermaid-svg-t61Z3C7qnWKeR3iv .node circle,#mermaid-svg-t61Z3C7qnWKeR3iv .node ellipse,#mermaid-svg-t61Z3C7qnWKeR3iv .node polygon,#mermaid-svg-t61Z3C7qnWKeR3iv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-t61Z3C7qnWKeR3iv .rough-node .label text,#mermaid-svg-t61Z3C7qnWKeR3iv .node .label text,#mermaid-svg-t61Z3C7qnWKeR3iv .image-shape .label,#mermaid-svg-t61Z3C7qnWKeR3iv .icon-shape .label{text-anchor:middle;}#mermaid-svg-t61Z3C7qnWKeR3iv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-t61Z3C7qnWKeR3iv .rough-node .label,#mermaid-svg-t61Z3C7qnWKeR3iv .node .label,#mermaid-svg-t61Z3C7qnWKeR3iv .image-shape .label,#mermaid-svg-t61Z3C7qnWKeR3iv .icon-shape .label{text-align:center;}#mermaid-svg-t61Z3C7qnWKeR3iv .node.clickable{cursor:pointer;}#mermaid-svg-t61Z3C7qnWKeR3iv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-t61Z3C7qnWKeR3iv .arrowheadPath{fill:#333333;}#mermaid-svg-t61Z3C7qnWKeR3iv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-t61Z3C7qnWKeR3iv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-t61Z3C7qnWKeR3iv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-t61Z3C7qnWKeR3iv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-t61Z3C7qnWKeR3iv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-t61Z3C7qnWKeR3iv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-t61Z3C7qnWKeR3iv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-t61Z3C7qnWKeR3iv .cluster text{fill:#333;}#mermaid-svg-t61Z3C7qnWKeR3iv .cluster span{color:#333;}#mermaid-svg-t61Z3C7qnWKeR3iv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-t61Z3C7qnWKeR3iv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-t61Z3C7qnWKeR3iv rect.text{fill:none;stroke-width:0;}#mermaid-svg-t61Z3C7qnWKeR3iv .icon-shape,#mermaid-svg-t61Z3C7qnWKeR3iv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-t61Z3C7qnWKeR3iv .icon-shape p,#mermaid-svg-t61Z3C7qnWKeR3iv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-t61Z3C7qnWKeR3iv .icon-shape .label rect,#mermaid-svg-t61Z3C7qnWKeR3iv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-t61Z3C7qnWKeR3iv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-t61Z3C7qnWKeR3iv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-t61Z3C7qnWKeR3iv :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
作用域层级
类作用域 Class Scope
方法作用域 Method Scope
块作用域 Block Scope
实例变量和静态变量 整个类内可见
方法参数和方法内局部变量 整个方法内可见
代码块内声明的变量 仅块内可见
5.2 块级作用域
在一个花括号{}内声明的变量,其作用域仅限该花括号内部:
public class ScopeDemo {
// 类作用域——instanceVar在整个类内可见
private int instanceVar = 100;
public void methodScope() {
// 方法作用域——methodVar在整个方法内可见
int methodVar = 200;
if (methodVar > 100) {
// 块作用域——blockVar仅在if块内可见
int blockVar = 300;
System.out.println(blockVar); // 可以访问
System.out.println(methodVar); // 可以访问
System.out.println(instanceVar); // 可以访问
}
System.out.println(methodVar); // 可以访问
System.out.println(instanceVar); // 可以访问
// System.out.println(blockVar); // 编译错误!blockVar已超出作用域
}
}
5.3 作用域嵌套与变量遮蔽
当内层作用域声明了与外层作用域同名的变量时,会发生变量遮蔽(Variable Shadowing)——内层变量会"遮蔽"外层变量:
public class ShadowingDemo {
private int value = 10; // 实例变量
public void test() {
int value = 20; // 局部变量,遮蔽了实例变量
System.out.println(value); // 输出20(局部变量)
System.out.println(this.value); // 输出10(通过this访问实例变量)
{
int value = 30; // 编译错误!
// 不能在嵌套块中声明与外部局部变量同名的变量
}
}
}
重要规则:
- 局部变量可以遮蔽实例变量(通过this关键字仍然可以访问实例变量)
- 方法参数可以遮蔽实例变量
- 同一方法内的嵌套代码块不能声明与外层局部变量同名的变量(编译错误)
5.4 循环中的作用域
循环变量有特殊的作用域规则:
// for循环中声明的变量——作用域仅限于for循环体
for (int i = 0; i < 5; i++) {
System.out.println(i); // 可以访问
}
// System.out.println(i); // 编译错误:i已超出作用域
// 不同循环可以使用相同的变量名——因为作用域不重叠
for (int i = 0; i < 3; i++) {
System.out.println("第一个循环:" + i);
}
for (int i = 0; i < 3; i++) { // 合法的,新的作用域
System.out.println("第二个循环:" + i);
}
// while循环中的变量——作用域是包含while的整个代码块
{
int j = 0;
while (j < 5) {
System.out.println(j);
j++;
}
System.out.println("最终:" + j); // 可以访问,输出5
}
5.5 作用域最佳实践
// ❌ 不推荐:变量作用域过大
public void badExample() {
String result; // 在方法开始就声明
// … 50行代码 …
result = computeResult(); // 实际使用时才赋值
// … 更多代码 …
}
// ✅ 推荐:最小化变量作用域
public void goodExample() {
// … 其他代码 …
String result = computeResult(); // 在第一次使用时才声明
// … 使用result的代码 …
}
**原则:变量应该在尽可能小的作用域内声明,在使用前才声明。**这样做的好处包括提高代码可读性、减少命名冲突、降低出错概率。
六、变量的生命周期
6.1 生命周期的三个阶段
变量的生命周期是指变量从创建到销毁的整个过程,分为三个阶段:
#mermaid-svg-lDEacyhI6yVpvvA3{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lDEacyhI6yVpvvA3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lDEacyhI6yVpvvA3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lDEacyhI6yVpvvA3 .error-icon{fill:#552222;}#mermaid-svg-lDEacyhI6yVpvvA3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lDEacyhI6yVpvvA3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lDEacyhI6yVpvvA3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lDEacyhI6yVpvvA3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lDEacyhI6yVpvvA3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lDEacyhI6yVpvvA3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lDEacyhI6yVpvvA3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lDEacyhI6yVpvvA3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lDEacyhI6yVpvvA3 .marker.cross{stroke:#333333;}#mermaid-svg-lDEacyhI6yVpvvA3 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lDEacyhI6yVpvvA3 p{margin:0;}#mermaid-svg-lDEacyhI6yVpvvA3 defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-lDEacyhI6yVpvvA3 g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-lDEacyhI6yVpvvA3 g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-lDEacyhI6yVpvvA3 g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-lDEacyhI6yVpvvA3 g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-lDEacyhI6yVpvvA3 g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-lDEacyhI6yVpvvA3 .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-lDEacyhI6yVpvvA3 .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-lDEacyhI6yVpvvA3 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-lDEacyhI6yVpvvA3 .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-lDEacyhI6yVpvvA3 .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-lDEacyhI6yVpvvA3 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-lDEacyhI6yVpvvA3 .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-lDEacyhI6yVpvvA3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lDEacyhI6yVpvvA3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lDEacyhI6yVpvvA3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lDEacyhI6yVpvvA3 .edgeLabel .label text{fill:#333;}#mermaid-svg-lDEacyhI6yVpvvA3 .label div .edgeLabel{color:#333;}#mermaid-svg-lDEacyhI6yVpvvA3 .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-lDEacyhI6yVpvvA3 .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-lDEacyhI6yVpvvA3 .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-lDEacyhI6yVpvvA3 .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-lDEacyhI6yVpvvA3 .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-lDEacyhI6yVpvvA3 .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lDEacyhI6yVpvvA3 .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lDEacyhI6yVpvvA3 #statediagram-barbEnd{fill:#333333;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lDEacyhI6yVpvvA3 .cluster-label,#mermaid-svg-lDEacyhI6yVpvvA3 .nodeLabel{color:#131300;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-lDEacyhI6yVpvvA3 .note-edge{stroke-dasharray:5;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-note text{fill:black;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram-note .nodeLabel{color:black;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagram .edgeLabel{color:red;}#mermaid-svg-lDEacyhI6yVpvvA3 #dependencyStart,#mermaid-svg-lDEacyhI6yVpvvA3 #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-lDEacyhI6yVpvvA3 .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lDEacyhI6yVpvvA3 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
读取/修改
垃圾回收
声明/创建
使用中
超出作用域
等待GC
分配内存空间\\n赋予初始值
程序读写变量
变量不再可达
由GC判断并回收
6.2 不同类型变量的生命周期
public class LifecycleDemo {
// 静态变量:类加载时创建,程序结束时销毁(最长)
private static int staticVar = initStatic();
// 实例变量:对象创建时创建,对象被GC回收时销毁
private int instanceVar = initInstance();
static {
System.out.println("[静态变量] 类加载时初始化");
}
public void method() {
// 局部变量:方法调用时创建,方法返回时销毁
int localVar = 10;
System.out.println("[局部变量] 方法执行时存在");
} // localVar在此处销毁
private static int initStatic() {
System.out.println("初始化静态变量");
return 100;
}
private int initInstance() {
System.out.println("初始化实例变量");
return 200;
}
public static void main(String[] args) {
System.out.println("— main方法开始 —");
LifecycleDemo demo = new LifecycleDemo();
demo.method();
System.out.println("— main方法结束 —");
}
}
输出顺序:
初始化静态变量
— main方法开始 —
初始化实例变量
[局部变量] 方法执行时存在
— main方法结束 —
6.3 垃圾回收与变量
Java的内存管理由垃圾回收器(Garbage Collector, GC)自动完成。GC的基本原理是:当一个对象不再被任何变量引用时,它就变成了垃圾回收的候选对象。
public class GCDemo {
public static void main(String[] args) {
// obj引用一个String对象
String obj = new String("Hello");
// obj仍然引用该对象——对象不可被回收
System.out.println(obj);
// 将obj设为null,断开引用
obj = null;
// 原来的String对象现在没有引用指向它——可以被GC回收
// (实际回收时机由JVM决定,不一定是立即回收)
// 作用域自然结束——变量超出作用域后,引用自动消失
{
String temp = new String("World");
System.out.println(temp);
} // temp超出作用域,"World"对象可以被回收
// 提示JVM进行垃圾回收(不保证立即执行)
System.gc();
}
}
垃圾回收器堆中对象变量引用垃圾回收器堆中对象变量引用#mermaid-svg-tTaKvTzIINsMH8mO{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tTaKvTzIINsMH8mO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tTaKvTzIINsMH8mO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tTaKvTzIINsMH8mO .error-icon{fill:#552222;}#mermaid-svg-tTaKvTzIINsMH8mO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tTaKvTzIINsMH8mO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tTaKvTzIINsMH8mO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tTaKvTzIINsMH8mO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tTaKvTzIINsMH8mO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tTaKvTzIINsMH8mO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tTaKvTzIINsMH8mO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tTaKvTzIINsMH8mO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tTaKvTzIINsMH8mO .marker.cross{stroke:#333333;}#mermaid-svg-tTaKvTzIINsMH8mO svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tTaKvTzIINsMH8mO p{margin:0;}#mermaid-svg-tTaKvTzIINsMH8mO .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-tTaKvTzIINsMH8mO text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-tTaKvTzIINsMH8mO .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-tTaKvTzIINsMH8mO .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-tTaKvTzIINsMH8mO .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-tTaKvTzIINsMH8mO .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-tTaKvTzIINsMH8mO #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-tTaKvTzIINsMH8mO .sequenceNumber{fill:white;}#mermaid-svg-tTaKvTzIINsMH8mO #sequencenumber{fill:#333;}#mermaid-svg-tTaKvTzIINsMH8mO #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-tTaKvTzIINsMH8mO .messageText{fill:#333;stroke:none;}#mermaid-svg-tTaKvTzIINsMH8mO .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-tTaKvTzIINsMH8mO .labelText,#mermaid-svg-tTaKvTzIINsMH8mO .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-tTaKvTzIINsMH8mO .loopText,#mermaid-svg-tTaKvTzIINsMH8mO .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-tTaKvTzIINsMH8mO .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-tTaKvTzIINsMH8mO .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-tTaKvTzIINsMH8mO .noteText,#mermaid-svg-tTaKvTzIINsMH8mO .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-tTaKvTzIINsMH8mO .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-tTaKvTzIINsMH8mO .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-tTaKvTzIINsMH8mO .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-tTaKvTzIINsMH8mO .actorPopupMenu{position:absolute;}#mermaid-svg-tTaKvTzIINsMH8mO .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-tTaKvTzIINsMH8mO .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-tTaKvTzIINsMH8mO .actor-man circle,#mermaid-svg-tTaKvTzIINsMH8mO line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-tTaKvTzIINsMH8mO :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}对象被引用,存活对象不可达内存释放String obj = new String("Hello")obj = null(断开引用)标记为垃圾回收内存
七、常量概述
7.1 什么是常量
常量(Constant)是指在程序运行期间其值不能被修改的变量。在Java中,使用final关键字来定义常量。
final double PI = 3.1415926535;
final int MAX_USERS = 1000;
final String APP_NAME = "教务管理系统";
常量的核心语义是:一旦赋值,永不改变。任何试图修改常量值的操作都会导致编译错误:
final int MAX = 100;
MAX = 200; // 编译错误:cannot assign a value to final variable
7.2 变量与常量的本质区别
#mermaid-svg-CR3HslHAMOnawitr{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CR3HslHAMOnawitr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CR3HslHAMOnawitr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CR3HslHAMOnawitr .error-icon{fill:#552222;}#mermaid-svg-CR3HslHAMOnawitr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CR3HslHAMOnawitr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CR3HslHAMOnawitr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CR3HslHAMOnawitr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CR3HslHAMOnawitr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CR3HslHAMOnawitr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CR3HslHAMOnawitr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CR3HslHAMOnawitr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CR3HslHAMOnawitr .marker.cross{stroke:#333333;}#mermaid-svg-CR3HslHAMOnawitr svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CR3HslHAMOnawitr p{margin:0;}#mermaid-svg-CR3HslHAMOnawitr .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-CR3HslHAMOnawitr .cluster-label text{fill:#333;}#mermaid-svg-CR3HslHAMOnawitr .cluster-label span{color:#333;}#mermaid-svg-CR3HslHAMOnawitr .cluster-label span p{background-color:transparent;}#mermaid-svg-CR3HslHAMOnawitr .label text,#mermaid-svg-CR3HslHAMOnawitr span{fill:#333;color:#333;}#mermaid-svg-CR3HslHAMOnawitr .node rect,#mermaid-svg-CR3HslHAMOnawitr .node circle,#mermaid-svg-CR3HslHAMOnawitr .node ellipse,#mermaid-svg-CR3HslHAMOnawitr .node polygon,#mermaid-svg-CR3HslHAMOnawitr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CR3HslHAMOnawitr .rough-node .label text,#mermaid-svg-CR3HslHAMOnawitr .node .label text,#mermaid-svg-CR3HslHAMOnawitr .image-shape .label,#mermaid-svg-CR3HslHAMOnawitr .icon-shape .label{text-anchor:middle;}#mermaid-svg-CR3HslHAMOnawitr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CR3HslHAMOnawitr .rough-node .label,#mermaid-svg-CR3HslHAMOnawitr .node .label,#mermaid-svg-CR3HslHAMOnawitr .image-shape .label,#mermaid-svg-CR3HslHAMOnawitr .icon-shape .label{text-align:center;}#mermaid-svg-CR3HslHAMOnawitr .node.clickable{cursor:pointer;}#mermaid-svg-CR3HslHAMOnawitr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CR3HslHAMOnawitr .arrowheadPath{fill:#333333;}#mermaid-svg-CR3HslHAMOnawitr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CR3HslHAMOnawitr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CR3HslHAMOnawitr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CR3HslHAMOnawitr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CR3HslHAMOnawitr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CR3HslHAMOnawitr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CR3HslHAMOnawitr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CR3HslHAMOnawitr .cluster text{fill:#333;}#mermaid-svg-CR3HslHAMOnawitr .cluster span{color:#333;}#mermaid-svg-CR3HslHAMOnawitr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CR3HslHAMOnawitr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CR3HslHAMOnawitr rect.text{fill:none;stroke-width:0;}#mermaid-svg-CR3HslHAMOnawitr .icon-shape,#mermaid-svg-CR3HslHAMOnawitr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CR3HslHAMOnawitr .icon-shape p,#mermaid-svg-CR3HslHAMOnawitr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CR3HslHAMOnawitr .icon-shape .label rect,#mermaid-svg-CR3HslHAMOnawitr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CR3HslHAMOnawitr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CR3HslHAMOnawitr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CR3HslHAMOnawitr :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
常量
声明: final int MAX = 100;
修改: MAX = 200; ✗
不可修改
变量
声明: int count = 10;
修改: count = 20; ✓
修改: count = 30; ✓
八、final关键字详解
8.1 final可以修饰什么
final是Java中一个功能丰富的关键字,可以修饰多种程序元素:
| 变量 | 值不可修改(常量) | final int MAX = 100; |
| 方法 | 方法不能被子类重写 | public final void method() {} |
| 类 | 类不能被继承 | public final class String {} |
| 参数 | 参数值在方法内不可修改 | public void method(final int x) {} |
本章聚焦于final修饰变量的用法。
8.2 final修饰局部变量
public void processData() {
final int threshold = 50; // 局部常量
if (threshold > 30) {
final String message = "超过阈值"; // 块内的局部常量
System.out.println(message);
// message = "新消息"; // 编译错误:不能修改
}
// threshold = 60; // 编译错误:不能修改
}
8.3 final修饰实例变量
实例常量有两种初始化方式:
public class Config {
// 方式一:声明时直接初始化
private final String appName = "教务系统";
// 方式二:在构造器中初始化(空白final)
private final String version;
private final int port;
public Config(String version, int port) {
this.version = version;
this.port = port;
}
// 编译错误:final实例变量必须在构造器执行完毕前被赋值
// 不能在普通方法中修改final实例变量
// public void setVersion(String v) { this.version = v; }
}
8.4 final修饰静态变量
public class AppConstants {
// 静态常量——推荐:声明时初始化
public static final String APP_NAME = "学生成绩管理系统";
public static final int DEFAULT_PAGE_SIZE = 20;
public static final double TAX_RATE = 0.13;
// 静态常量也可以用在静态初始化块中赋值
public static final long TIMESTAMP;
static {
TIMESTAMP = System.currentTimeMillis();
}
}
九、final变量与final引用
9.1 基本类型与引用类型的区别
这是理解final关键字最容易出错的地方。final修饰基本类型变量和修饰引用类型变量,含义有微妙但重要的区别:
| 基本类型(int、double等) | 数值不可修改 | 变量中存储的值 |
| 引用类型(String、对象等) | 引用地址不可修改 | 变量中存储的引用(指针) |
9.2 基本类型常量
final int NUMBER = 100;
// NUMBER = 200; // 编译错误:不能修改值
基本类型的常量非常简单——值不可改变。
9.3 引用类型常量
final StringBuilder builder = new StringBuilder("Hello");
// builder = new StringBuilder("World"); // 编译错误:不能修改引用
builder.append(" World"); // 合法!修改对象内容,不是修改引用
builder.append(" Java"); // 合法!
System.out.println(builder); // 输出:Hello World Java
#mermaid-svg-DPUBWN2SNFZem43a{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DPUBWN2SNFZem43a .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DPUBWN2SNFZem43a .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DPUBWN2SNFZem43a .error-icon{fill:#552222;}#mermaid-svg-DPUBWN2SNFZem43a .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DPUBWN2SNFZem43a .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DPUBWN2SNFZem43a .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DPUBWN2SNFZem43a .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DPUBWN2SNFZem43a .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DPUBWN2SNFZem43a .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DPUBWN2SNFZem43a .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DPUBWN2SNFZem43a .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DPUBWN2SNFZem43a .marker.cross{stroke:#333333;}#mermaid-svg-DPUBWN2SNFZem43a svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DPUBWN2SNFZem43a p{margin:0;}#mermaid-svg-DPUBWN2SNFZem43a .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-DPUBWN2SNFZem43a .cluster-label text{fill:#333;}#mermaid-svg-DPUBWN2SNFZem43a .cluster-label span{color:#333;}#mermaid-svg-DPUBWN2SNFZem43a .cluster-label span p{background-color:transparent;}#mermaid-svg-DPUBWN2SNFZem43a .label text,#mermaid-svg-DPUBWN2SNFZem43a span{fill:#333;color:#333;}#mermaid-svg-DPUBWN2SNFZem43a .node rect,#mermaid-svg-DPUBWN2SNFZem43a .node circle,#mermaid-svg-DPUBWN2SNFZem43a .node ellipse,#mermaid-svg-DPUBWN2SNFZem43a .node polygon,#mermaid-svg-DPUBWN2SNFZem43a .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DPUBWN2SNFZem43a .rough-node .label text,#mermaid-svg-DPUBWN2SNFZem43a .node .label text,#mermaid-svg-DPUBWN2SNFZem43a .image-shape .label,#mermaid-svg-DPUBWN2SNFZem43a .icon-shape .label{text-anchor:middle;}#mermaid-svg-DPUBWN2SNFZem43a .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DPUBWN2SNFZem43a .rough-node .label,#mermaid-svg-DPUBWN2SNFZem43a .node .label,#mermaid-svg-DPUBWN2SNFZem43a .image-shape .label,#mermaid-svg-DPUBWN2SNFZem43a .icon-shape .label{text-align:center;}#mermaid-svg-DPUBWN2SNFZem43a .node.clickable{cursor:pointer;}#mermaid-svg-DPUBWN2SNFZem43a .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DPUBWN2SNFZem43a .arrowheadPath{fill:#333333;}#mermaid-svg-DPUBWN2SNFZem43a .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DPUBWN2SNFZem43a .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DPUBWN2SNFZem43a .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DPUBWN2SNFZem43a .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DPUBWN2SNFZem43a .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DPUBWN2SNFZem43a .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DPUBWN2SNFZem43a .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DPUBWN2SNFZem43a .cluster text{fill:#333;}#mermaid-svg-DPUBWN2SNFZem43a .cluster span{color:#333;}#mermaid-svg-DPUBWN2SNFZem43a div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DPUBWN2SNFZem43a .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DPUBWN2SNFZem43a rect.text{fill:none;stroke-width:0;}#mermaid-svg-DPUBWN2SNFZem43a .icon-shape,#mermaid-svg-DPUBWN2SNFZem43a .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DPUBWN2SNFZem43a .icon-shape p,#mermaid-svg-DPUBWN2SNFZem43a .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DPUBWN2SNFZem43a .icon-shape .label rect,#mermaid-svg-DPUBWN2SNFZem43a .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DPUBWN2SNFZem43a .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DPUBWN2SNFZem43a .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DPUBWN2SNFZem43a :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
final StringBuilder builder
固定指向
append
不能指向
builder 引用不可修改
StringBuilder对象内容可以修改
Hello World Java
新的StringBuilder对象
核心理解:final锁定的是引用(箭头),而不是被引用的对象本身。
9.4 经典案例:final数组
final int[] scores = {85, 90, 78, 92};
// scores = new int[]{70, 80, 90}; // 编译错误:不能修改引用
// 但是可以修改数组元素!
scores[0] = 88; // 合法
scores[1] = 95; // 合法
System.out.println(Arrays.toString(scores)); // [88, 95, 78, 92]
9.5 String的特殊性:不可变对象
String是Java中的不可变类(Immutable Class),即String对象一旦创建,其内容就不可修改。因此当final和String组合时:
final String text = "Hello";
// text = "World"; // 编译错误:不能修改引用
// String没有修改内容的方法
// text.??? // 所有String方法都返回新String,不修改原对象
// 所以 final String 实现了彻底的不可变——引用和内容都不能修改
十、静态常量:static final组合
10.1 为什么需要static final
static final组合定义的常量是Java中最经典的常量形式。static确保常量属于类而不是对象(全局唯一),final确保值不可修改。
public class MathConstants {
// 静态常量——属于类的全局常量
public static final double PI = 3.141592653589793;
public static final double E = 2.718281828459045;
// 仅static(类变量,可修改)
public static double tolerance = 0.0001;
// 仅final(实例常量,每个对象一份)
public final double value;
public MathConstants(double value) {
this.value = value;
}
}
10.2 static final的使用场景
// 场景一:数学常量
public static final double PI = 3.141592653589793;
// 场景二:配置参数
public static final int MAX_RETRY_TIMES = 3;
public static final long CACHE_EXPIRE_SECONDS = 3600;
// 场景三:状态码
public static final int STATUS_SUCCESS = 200;
public static final int STATUS_NOT_FOUND = 404;
public static final int STATUS_ERROR = 500;
// 场景四:错误消息
public static final String ERROR_INVALID_INPUT = "输入参数无效";
public static final String ERROR_DB_CONNECTION = "数据库连接失败";
// 场景五:枚举替代值
public static final int ROLE_ADMIN = 1;
public static final int ROLE_USER = 2;
public static final int ROLE_GUEST = 3;
10.3 常量定义的最佳实践
在实际项目中,通常将所有常量集中管理:
/**
* 系统常量定义类
*/
public final class SystemConstants {
// 私有构造器,防止实例化
private SystemConstants() {
throw new UnsupportedOperationException("常量类不允许实例化");
}
// ========== 应用信息 ==========
public static final String APP_NAME = "学生成绩管理系统";
public static final String APP_VERSION = "3.2.1";
// ========== 分页配置 ==========
public static final int DEFAULT_PAGE_SIZE = 20;
public static final int MAX_PAGE_SIZE = 100;
// ========== 文件上传限制 ==========
public static final long MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
public static final String[] ALLOWED_EXTENSIONS = {".pdf", ".doc", ".docx"};
// ========== 业务状态码 ==========
public static final int CODE_SUCCESS = 200;
public static final int CODE_BAD_REQUEST = 400;
public static final int CODE_UNAUTHORIZED = 401;
public static final int CODE_SERVER_ERROR = 500;
}
十一、为何使用常量
11.1 消灭魔术数字(Magic Numbers)
魔术数字是指直接出现在代码中的、没有明确含义的数值。它们让代码难以理解和维护。
// ❌ 充满魔术数字的代码——难以阅读和维护
public double calculateArea(double radius) {
return 3.1415926535 * radius * radius;
}
public void setUserStatus(int status) {
if (status == 1) {
// 激活用户
} else if (status == 2) {
// 冻结用户
} else if (status == 3) {
// 删除用户
}
}
// ✅ 使用常量——清晰、可维护
public static final double PI = 3.1415926535;
public static final int STATUS_ACTIVE = 1;
public static final int STATUS_FROZEN = 2;
public static final int STATUS_DELETED = 3;
public double calculateArea(double radius) {
return PI * radius * radius;
}
public void setUserStatus(int status) {
if (status == STATUS_ACTIVE) {
// 激活用户
} else if (status == STATUS_FROZEN) {
// 冻结用户
} else if (status == STATUS_DELETED) {
// 删除用户
}
}
11.2 集中化配置管理
将常量集中定义,修改时只需要改一处,系统其余部分自动生效:
// 分散的硬编码
public class ServiceA {
public void connect() {
int timeout = 5000; // 超时时间
// …
}
}
public class ServiceB {
public void connect() {
int timeout = 5000; // 另一个服务也写了5000
// …
}
}
// 如果要改为3000,需要到处修改,容易遗漏
// 集中管理
public class AppConfig {
public static final int CONNECTION_TIMEOUT = 5000;
public static final String DB_URL = "jdbc:mysql://localhost:3306/edu";
public static final String DB_USER = "admin";
public static final String DB_PASSWORD = "secure123";
}
public class ServiceA {
public void connect() {
int timeout = AppConfig.CONNECTION_TIMEOUT;
// …
}
}
public class ServiceB {
public void connect() {
int timeout = AppConfig.CONNECTION_TIMEOUT;
// …
}
}
11.3 增强代码可读性
使用有意义的常量名代替数值,让代码意图一目了然:
// ❌ 含义不明确
if (user.getAge() >= 18) { ... }
if (order.getAmount() > 999) { ... }
if (attemptCount <= 3) { ... }
// ✅ 含义明确
public static final int LEGAL_ADULT_AGE = 18;
public static final double FREE_SHIPPING_THRESHOLD = 999.0;
public static final int MAX_LOGIN_ATTEMPTS = 3;
if (user.getAge() >= LEGAL_ADULT_AGE) { ... }
if (order.getAmount() > FREE_SHIPPING_THRESHOLD) { ... }
if (attemptCount <= MAX_LOGIN_ATTEMPTS) { ... }
11.4 降低出错概率
// ❌ 容易写错
if (dayOfWeek == 7) { ... } // 7是周日还是周六?
if (month == 12) { ... } // 12是12月,容易理解
// ✅ 不容易写错
public static final int SUNDAY = 7;
public static final int DECEMBER = 12;
if (dayOfWeek == SUNDAY) { ... }
十二、编译时常量
12.1 什么是编译时常量
编译时常量(Compile-Time Constant)是指值在编译阶段就能确定的常量。Java编译器会对编译时常量进行内联优化——在编译时将常量值直接替换到引用处,而不是在运行时查找。
一个变量要成为编译时常量,必须同时满足:
// 这些都是编译时常量
public static final int MAX = 100;
public static final String NAME = "Java";
public static final double RATE = 0.05;
public static final int CALCULATED = 60 * 60 * 24; // 常量表达式
// 这些不是编译时常量
public static final long CURRENT_TIME = System.currentTimeMillis(); // 运行时确定
public static final int RANDOM = new Random().nextInt(); // 运行时确定
public static final String INPUT = new Scanner(System.in).nextLine();// 运行时确定
12.2 内联优化的效果
// 类A中定义常量
public class A {
public static final int VALUE = 100;
}
// 类B中使用常量
public class B {
public void test() {
int x = A.VALUE; // 编译后实际变为:int x = 100;
System.out.println(x);
}
}
内联优化的一个重要后果:如果修改了A类中VALUE的值后只重新编译A类而不编译B类,B类中使用的仍然是旧值。因此,如果常量值可能变化,应考虑改用非编译时常量(如使用方法返回值)。
12.3 switch-case中的编译时常量
switch语句的case标签必须是编译时常量:
public static final int STATUS_ACTIVE = 1;
public static final int STATUS_INACTIVE = 2;
public static final int STATUS_DELETED = 3;
public void handleStatus(int status) {
switch (status) {
case STATUS_ACTIVE: // ✓ 编译时常量
activateUser();
break;
case STATUS_INACTIVE: // ✓ 编译时常量
deactivateUser();
break;
case STATUS_DELETED: // ✓ 编译时常量
deleteUser();
break;
}
}
十三、空白final变量
13.1 什么是空白final
空白final变量(Blank Final Variable)是指在声明时没有赋予初始值的final变量。它必须在每个构造器中被赋值,且只能赋值一次。
public class Document {
private final String id; // 空白final
private final String title; // 空白final
private final long createdAt; // 空白final
public Document(String id, String title) {
this.id = id; // 在构造器中初始化
this.title = title;
this.createdAt = System.currentTimeMillis();
// this.id = "newId"; // 编译错误:final变量只能赋值一次
}
// 如果有多个构造器,每个都必须初始化所有空白final变量
public Document(String title) {
this.id = UUID.randomUUID().toString(); // 自动生成ID
this.title = title;
this.createdAt = System.currentTimeMillis();
}
// 编译错误:如果某个构造器遗漏了空白final的初始化
// public Document() {
// // 缺少 id、title、createdAt 的初始化
// }
}
13.2 空白final的应用场景
空白final特别适合**不可变对象(Immutable Object)**的设计模式:
/**
* 不可变用户对象——所有属性一旦在构造时确定,就永远不变
*/
public class ImmutableUser {
private final String username;
private final String email;
private final int age;
private final LocalDate registrationDate;
public ImmutableUser(String username, String email, int age) {
// 参数校验
if (username == null || username.isEmpty()) {
throw new IllegalArgumentException("用户名不能为空");
}
if (age < 0 || age > 150) {
throw new IllegalArgumentException("年龄不合法");
}
// 防御性复制
this.username = username;
this.email = email;
this.age = age;
this.registrationDate = LocalDate.now();
}
// 只提供getter,不提供setter
public String getUsername() { return username; }
public String getEmail() { return email; }
public int getAge() { return age; }
public LocalDate getRegistrationDate() { return registrationDate; }
}
13.3 空白final与静态final
静态的空白final变量必须在静态初始化块中赋值:
public class AppConfig {
// 静态空白final——在静态初始化块中赋值
public static final String CONFIG_PATH;
public static final int MAX_CONNECTIONS;
public static final boolean DEBUG_MODE;
static {
// 可以读取配置文件、计算复杂逻辑来确定常量值
Properties props = loadProperties();
CONFIG_PATH = props.getProperty("config.path", "/etc/app/config");
MAX_CONNECTIONS = Integer.parseInt(
props.getProperty("max.connections", "100"));
DEBUG_MODE = Boolean.parseBoolean(
props.getProperty("debug.mode", "false"));
}
private static Properties loadProperties() {
// 加载配置文件的逻辑
return new Properties();
}
}
十四、var类型推断(Java 10+)
14.1 var关键字简介
Java 10引入了局部变量类型推断(Local-Variable Type Inference),允许使用var关键字声明局部变量而无需显式指定类型。编译器会根据赋值表达式的右侧自动推断变量的类型。
// 传统写法
String name = "张三";
int age = 25;
List<String> names = new ArrayList<>();
// 使用var(Java 10+)
var name = "张三"; // 推断为String
var age = 25; // 推断为int
var names = new ArrayList<String>(); // 推断为ArrayList<String>
14.2 var vs final var
var可以与final组合使用,声明不可修改的局部变量:
// 不可修改的局部变量——类型由编译器推断
final var PI = 3.14159; // 推断为double
final var MAX_SIZE = 1000; // 推断为int
final var appName = "管理系统"; // 推断为String
// PI = 3.14; // 编译错误:final变量不能修改
14.3 var的使用限制
var虽然方便,但有严格的使用限制:
| 只能用于局部变量 | 不能用于字段、方法参数、返回类型 | var name;(类字段)❌ |
| 必须初始化 | 编译器需要初始值来推断类型 | var x; ❌ |
| 不能初始化为null | 编译器无法推断null的类型 | var x = null; ❌ |
| 不能用于复合声明 | 一行声明多个变量不能用var | var a = 1, b = 2; ❌ |
| Lambda表达式 | 不能用于Lambda表达式参数(Java 11+允许) | – |
// var的正确使用场景
var user = new User("张三", 25); // 对象创建
var list = List.of("A", "B", "C"); // 集合
var input = new FileInputStream("a.txt"); // IO流
var result = computeSomething(); // 方法返回值
// var的不恰当使用——降低可读性
var x = compute(); // x是什么类型?不清晰
// 此时应该使用显式类型声明
ResultType x = compute(); // 清晰明了
14.4 var使用建议
// ✅ 推荐使用var的场景
// 场景1:类型名很长,右侧已经明确了类型
var userMap = new HashMap<Integer, User>();
// 场景2:try-with-resources
try (var reader = new BufferedReader(new FileReader("data.txt"))) {
// …
}
// 场景3:不可实例化的类型
var list = Collections.emptyList();
// ❌ 不推荐使用var的场景
// 场景1:右侧信息不足以推断类型
var data = service.getData(); // 返回类型不清楚
// 场景2:基本类型,显式声明更清晰
// var count = 0; 不如
int count = 0;
十五、变量初始化最佳实践
15.1 总是初始化局部变量
// ❌ 坏习惯:延迟初始化
int result;
if (condition) {
result = calculateA();
} else {
result = calculateB();
}
// 容易忘记else分支导致编译错误
// ✅ 好习惯:声明时初始化或使用三元表达式
int result = condition ? calculateA() : calculateB();
// 或者立即赋予默认值
int result = 0;
if (condition) {
result = calculateA();
} else {
result = calculateB();
}
15.2 使用final优先
对于不应该被修改的变量,应该立即标注为final:
// ❌ 让读者自己去判断这个变量是否会被修改
String databaseUrl = config.getProperty("db.url");
int maxAttempts = Integer.parseInt(config.getProperty("max.attempts"));
// ✅ 明确表达意图:这些值在初始化后不会改变
final String databaseUrl = config.getProperty("db.url");
final int maxAttempts = Integer.parseInt(config.getProperty("max.attempts"));
15.3 选择合适的作用域
// ❌ 作用域过大
public void processOrders(List<Order> orders) {
double totalPrice = 0; // 整个方法都能访问
int orderCount = orders.size(); // 整个方法都能访问
String report = ""; // 整个方法都能访问
for (Order order : orders) {
totalPrice += order.getPrice();
}
// 100行之后才使用report
report = buildReport(totalPrice, orderCount);
}
// ✅ 作用域最小化
public void processOrders(List<Order> orders) {
int orderCount = orders.size();
double totalPrice = 0;
for (Order order : orders) {
totalPrice += order.getPrice();
}
String report = buildReport(totalPrice, orderCount);
// report只在需要使用时才声明
}
15.4 一行一个变量
// ❌ 一行多个变量——难以阅读和调试
int a = 1, b = 2, c = 3;
String x = "hello", y = "world";
// ✅ 每行一个变量——清晰明了
int a = 1;
int b = 2;
int c = 3;
String x = "hello";
String y = "world";
15.5 变量声明顺序
在类中,建议按以下顺序声明变量:
public class OrderService {
// 1. 静态常量
public static final int MAX_ITEMS = 100;
public static final String SERVICE_NAME = "OrderService";
// 2. 静态变量
private static int activeOrderCount = 0;
private static Logger logger = LoggerFactory.getLogger(OrderService.class);
// 3. 实例常量
private final String orderId;
private final LocalDateTime createdAt;
// 4. 实例变量
private List<OrderItem> items;
private OrderStatus status;
private double totalAmount;
// 5. 构造器…
// 6. 方法…
}
十六、综合案例:学生成绩管理系统
下面通过一个综合案例,将本章所学知识点融会贯通:
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* 常量定义类
*/
public final class GradeConstants {
private GradeConstants() {}
// 编译时常量
public static final double PASS_SCORE = 60.0;
public static final double FULL_SCORE = 100.0;
public static final int MAX_COURSE_COUNT = 10;
// 等级常量
public static final String GRADE_A = "优秀";
public static final String GRADE_B = "良好";
public static final String GRADE_C = "中等";
public static final String GRADE_D = "及格";
public static final String GRADE_F = "不及格";
}
/**
* 学生成绩——不可变对象设计
*/
public class StudentGrade {
// 实例常量(空白final)
private final String studentId; // 学号
private final String courseName; // 课程名
private final double score; // 分数
private final String grade; // 等级
private final LocalDateTime recordTime; // 录入时间
public StudentGrade(String studentId, String courseName, double score) {
// 参数校验
if (studentId == null || studentId.isBlank()) {
throw new IllegalArgumentException("学号不能为空");
}
if (score < 0 || score > GradeConstants.FULL_SCORE) {
throw new IllegalArgumentException("分数必须在0-100之间");
}
this.studentId = studentId;
this.courseName = courseName;
this.score = score;
this.grade = calculateGrade(score); // 根据分数计算等级
this.recordTime = LocalDateTime.now();
}
private String calculateGrade(double score) {
if (score >= 90) return GradeConstants.GRADE_A;
if (score >= 80) return GradeConstants.GRADE_B;
if (score >= 70) return GradeConstants.GRADE_C;
if (score >= GradeConstants.PASS_SCORE) return GradeConstants.GRADE_D;
return GradeConstants.GRADE_F;
}
// 只提供getter方法,不提供setter
public String getStudentId() { return studentId; }
public String getCourseName() { return courseName; }
public double getScore() { return score; }
public String getGrade() { return grade; }
public LocalDateTime getRecordTime() { return recordTime; }
/**
* 判断是否及格
*/
public boolean isPassed() {
return score >= GradeConstants.PASS_SCORE;
}
}
/**
* 成绩管理服务
*/
public class GradeService {
// 静态变量——统计所有实例
private static int totalRecordsProcessed = 0;
// 实例变量
private final List<StudentGrade> grades = new ArrayList<>();
private String className;
public GradeService(String className) {
this.className = className;
}
public void addGrade(StudentGrade grade) {
// 局部变量——仅在方法内使用
final int beforeSize = grades.size(); // final局部变量
grades.add(grade);
totalRecordsProcessed++;
if (grades.size() > beforeSize) {
System.out.println("成绩添加成功");
}
}
public double calculateAverage() {
// 使用var进行类型推断(Java 10+)
var totalScore = 0.0; // 编译时已确定类型为double
for (var grade : grades) { // 增强for循环中的var
totalScore += grade.getScore();
}
// 作用域最小化——在需要时才声明变量
var averageScore = grades.isEmpty() ? 0.0 : totalScore / grades.size();
return averageScore;
}
public static int getTotalRecordsProcessed() {
return totalRecordsProcessed;
}
}
#mermaid-svg-6tjgUHe3EcC6Y8kd{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6tjgUHe3EcC6Y8kd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6tjgUHe3EcC6Y8kd .error-icon{fill:#552222;}#mermaid-svg-6tjgUHe3EcC6Y8kd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6tjgUHe3EcC6Y8kd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6tjgUHe3EcC6Y8kd .marker.cross{stroke:#333333;}#mermaid-svg-6tjgUHe3EcC6Y8kd svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6tjgUHe3EcC6Y8kd p{margin:0;}#mermaid-svg-6tjgUHe3EcC6Y8kd g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-6tjgUHe3EcC6Y8kd g.classGroup text .title{font-weight:bolder;}#mermaid-svg-6tjgUHe3EcC6Y8kd .cluster-label text{fill:#333;}#mermaid-svg-6tjgUHe3EcC6Y8kd .cluster-label span{color:#333;}#mermaid-svg-6tjgUHe3EcC6Y8kd .cluster-label span p{background-color:transparent;}#mermaid-svg-6tjgUHe3EcC6Y8kd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6tjgUHe3EcC6Y8kd .cluster text{fill:#333;}#mermaid-svg-6tjgUHe3EcC6Y8kd .cluster span{color:#333;}#mermaid-svg-6tjgUHe3EcC6Y8kd .nodeLabel,#mermaid-svg-6tjgUHe3EcC6Y8kd .edgeLabel{color:#131300;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-6tjgUHe3EcC6Y8kd .label text{fill:#131300;}#mermaid-svg-6tjgUHe3EcC6Y8kd .labelBkg{background:#ECECFF;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-6tjgUHe3EcC6Y8kd .classTitle{font-weight:bolder;}#mermaid-svg-6tjgUHe3EcC6Y8kd .node rect,#mermaid-svg-6tjgUHe3EcC6Y8kd .node circle,#mermaid-svg-6tjgUHe3EcC6Y8kd .node ellipse,#mermaid-svg-6tjgUHe3EcC6Y8kd .node polygon,#mermaid-svg-6tjgUHe3EcC6Y8kd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6tjgUHe3EcC6Y8kd .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd g.clickable{cursor:pointer;}#mermaid-svg-6tjgUHe3EcC6Y8kd g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-6tjgUHe3EcC6Y8kd g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-6tjgUHe3EcC6Y8kd .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-6tjgUHe3EcC6Y8kd .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-6tjgUHe3EcC6Y8kd .dashed-line{stroke-dasharray:3;}#mermaid-svg-6tjgUHe3EcC6Y8kd .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-6tjgUHe3EcC6Y8kd #compositionStart,#mermaid-svg-6tjgUHe3EcC6Y8kd .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd #compositionEnd,#mermaid-svg-6tjgUHe3EcC6Y8kd .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd #dependencyStart,#mermaid-svg-6tjgUHe3EcC6Y8kd .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd #dependencyStart,#mermaid-svg-6tjgUHe3EcC6Y8kd .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd #extensionStart,#mermaid-svg-6tjgUHe3EcC6Y8kd .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd #extensionEnd,#mermaid-svg-6tjgUHe3EcC6Y8kd .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd #aggregationStart,#mermaid-svg-6tjgUHe3EcC6Y8kd .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd #aggregationEnd,#mermaid-svg-6tjgUHe3EcC6Y8kd .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd #lollipopStart,#mermaid-svg-6tjgUHe3EcC6Y8kd .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd #lollipopEnd,#mermaid-svg-6tjgUHe3EcC6Y8kd .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-6tjgUHe3EcC6Y8kd .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-6tjgUHe3EcC6Y8kd .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6tjgUHe3EcC6Y8kd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6tjgUHe3EcC6Y8kd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6tjgUHe3EcC6Y8kd :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
管理
使用
使用
«final class»
GradeConstants
+PASS_SCORE: double
+FULL_SCORE: double
+MAX_COURSE_COUNT: int
+GRADE_A~F: String
«immutable»
StudentGrade
-studentId: String
-courseName: String
-score: double
-grade: String
-recordTime: LocalDateTime
+isPassed() : : boolean
GradeService
-totalRecordsProcessed: int
-grades: List<StudentGrade>
-className: String
+addGrade(StudentGrade) : : void
+calculateAverage() : : double
本章关键词回顾
| 变量(Variable) | 用于存储数据的一块命名内存空间 |
| 局部变量 | 在方法或代码块内部声明的变量,存储在栈中,无默认值 |
| 实例变量 | 在类中声明、无static修饰的变量,属于对象,存储在堆中 |
| 静态变量 | 用static修饰的变量,属于类,所有实例共享 |
| 作用域(Scope) | 变量有效的代码范围,由花括号决定 |
| 变量遮蔽(Shadowing) | 内层变量与外层变量同名时,内层变量覆盖外层变量 |
| 生命周期 | 变量从创建到销毁的整个过程 |
| 垃圾回收(GC) | JVM自动回收不再使用的对象内存 |
| final | 声明常量的关键字,表示"一旦赋值,永不改变" |
| 常量(Constant) | 使用final修饰的、值不可修改的变量 |
| 编译时常量 | 值在编译期可确定的常量,会被内联优化 |
| 空白final | 声明时未初始化的final变量,必须在构造器中初始化 |
| 魔术数字 | 代码中直接出现的、含义不明的数值 |
| var | Java 10引入的局部变量类型推断关键字 |
思考与练习
基础练习
public class Test {
private int count;
private static String name;
public void method(int x) {
int y;
System.out.println(y); // 错误1
if (x > 0) {
int y = 10; // 错误2
String name = "test";
}
final int z;
z = 100;
z = 200; // 错误3
}
}
public class ScopeTest {
private static int value = 100;
public static void main(String[] args) {
int value = 200;
System.out.println(value);
{
int value = 300;
System.out.println(value);
}
}
}
进阶练习
设计一个BankAccount(银行账户)类,要求:
- 使用final关键字确保账号(accountNumber)在创建后不可修改
- 使用静态常量定义银行名称和最低余额限制
- 提供一个withdraw(取款)方法,不允许取款后余额低于最低限制
- 使用静态变量统计所有账户的总余额
分析以下代码,判断每个final修饰的效果:
final List<String> names = new ArrayList<>();
names.add("张三");
names.add("李四");
names = new ArrayList<>(); // 能否编译通过?
思考题
为什么Java设计了空白final机制?它解决了什么实际问题?
String是final类,String对象的内容也不可变。那么final String和普通的String在行为上有区别吗?为什么?
下一篇文章预览
掌握了变量与常量的基础知识后,下一篇文章我们将深入探讨运算符与表达式——从算术运算到逻辑运算,从运算符优先级到类型转换规则。你将学到如何使用Java丰富的运算符来构建复杂的数据处理逻辑,以及如何避免常见的运算符陷阱。
本章完 | 变量是数据的基础容器,常量是稳定的数据锚点。理解它们,你就掌握了Java数据管理的核心机制。
网硕互联帮助中心







评论前必须登录!
注册