乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 Java概述与环境搭建

    • Java概述与环境搭建
    • Java语言概述
    • 解释型语言与编译型语言对比
    • JDK安装与配置
    • JDK、JRE、JVM 详解
    • HelloWorld程序详解
    • IDE 介绍
  • 第2章 标识符与基本数据类型

    • 章节导读
    • 变量概述
    • 常量概述
    • 基本类型与包装类
    • 字节型 byte
    • 短整型 short
    • 整型 int
    • 长整型 long
    • 单精度浮点型 float
    • 双精度浮点型 double
    • 字符型 char
    • 布尔型 boolean
    • 类型转换
  • 第3章 运算符与表达式

    • 章节导读
    • 算术运算符
    • 赋值运算符
    • 关系运算符
    • 逻辑运算符
    • 位运算符
    • 条件运算符
    • 运算符优先级
    • 表达式
  • 第4章 流程控制

    • 章节导读
    • 常见的程序运行流程
    • if-else 选择结构
    • switch 多分支选择
    • while 循环
    • do-while 循环
    • for 循环
    • break 与 continue
  • 第5章 数组

    • 章节导读
    • 一维数组
    • 多维数组
    • Arrays 工具类
  • 第6章 类与对象

    • 章节导读
    • 类与对象
    • 方法定义与调用
    • 构造方法
    • 封装
    • 访问修饰符
    • package 与 import
    • static 关键字
    • this 关键字
    • 参数传递 详解
    • 枚举
    • 成员内部类
    • 局部内部类
    • 静态内部类
    • 匿名内部类
  • 第7章 接口与继承

    • 章节导读
    • 继承
    • super 关键字
    • final 关键字
    • 多态
    • 向上转型与向下转型
    • 抽象类
    • 接口
    • 抽象类与接口对比
  • 第8章 注解

    • 章节导读
    • 注解基础
    • 元注解详解
    • 自定义注解
  • 第9章 常用类

    • 章节导读:Java 常用类
    • Object 类:万类之祖
    • 包装类:基本类型的对象化
    • String:不可变的字符串
    • StringBuffer:线程安全的可变字符串
    • StringBuilder:可变的字符串构建器
    • Math:数学运算工具类
    • Random:伪随机数生成器
    • 大数值运算 详解
    • 日期时间API 详解
  • 第10章 异常机制

    • 章节导读
    • 异常体系与分类
    • try-catch-finally
    • try-with-resources
    • throws 与 throw
    • 自定义异常
  • 第11章 泛型

    • 章节导读
    • 泛型基础
    • 通配符与PECS原则
    • 类型擦除
  • 第12章 集合框架

    • 章节导读
    • 集合框架概述
    • ArrayList
    • LinkedList
    • HashMap 详解
    • LinkedHashMap 详解
    • TreeMap 详解
    • HashSet
    • TreeSet 详解
    • TreeSet 与 Comparable
    • Collections 工具类详解
  • 第13章 IO流

    • 章节导读
    • IO流概述
    • 字节流
    • 字符流
    • 缓冲流
    • 转换流 详解
    • 序列化 详解
    • NIO与Files 详解
    • NIO与Files工具类
  • 第14章 多线程与并发

    • 第十六章 多线程与并发 —— 章节导读
    • 线程基础详解
    • synchronized 详解
    • Lock 与显式锁详解
    • volatile 详解
    • wait 与 notify 详解
    • ThreadLocal详解
    • 原子类详解
    • 并发工具类详解
    • 线程池详解
  • 第15章 反射

    • 章节导读
    • 反射概述与 Class 对象
    • Constructor 与对象创建
    • Field与Method详解
    • 反射应用详解
  • 第16章 JDK8新特性

    • 章节导读
    • Lambda 表达式
    • Stream API 基础
    • Stream API 高级详解
    • Optional 详解
    • 新日期时间API详解
  • 第17章 JDK9-11新特性

    • 章节导读
    • 模块化系统 — Project Jigsaw(JDK 9)
    • var 局部变量类型推断(JDK 10)
    • 集合工厂方法与增强(JDK 9 / 10 / 11)
    • 接口增强:private 方法(JDK 9)
    • Stream API 增强(JDK 9)
    • Optional 增强(JDK 9 / 10 / 11)
    • String 新增方法(JDK 11)
    • HTTP Client 与 Files 增强(JDK 11)
    • 直接运行 Java 源文件 — JEP 330(JDK 11)
  • 第18章 JDK12-17新特性

    • 章节导读
    • Switch 表达式(JDK 12 预览 / JDK 14 正式)
    • 文本块 Text Blocks(JDK 13 预览 / JDK 15 正式)
    • Records 记录类(JDK 14 预览 / JDK 16 正式)
    • 密封类 Sealed Classes(JDK 15 预览 / JDK 17 正式)
    • instanceof 模式匹配(JDK 14 预览 / JDK 16 正式)
    • Switch 模式匹配 — Pattern Matching for switch(JDK 17 预览 / JDK 21 正式)
    • Helpful NPE 与 String 增强(JDK 12 / JDK 14 / JDK 15)
    • Stream 增强(JDK 12 / JDK 16)
    • 日期时间增强 — Day Period 支持(JDK 16)
  • 第19章 JDK18-21新特性

    • 章节导读
    • 虚拟线程(JDK 19 预览 / JDK 20 第二预览 / JDK 21 正式)
    • 序列集合(JDK 21 正式)
    • Switch 模式匹配(JDK 17 预览 / JDK 18 第二预览 / JDK 20 第四预览 / JDK 21 正式)
    • Record 模式匹配(JDK 19 预览 / JDK 20 第二预览 / JDK 21 正式)
    • 未命名模式与变量(JDK 21 预览 / JDK 22 正式)
  • 第20章 JDK 22-25 新特性

    • 章节导读
    • 字符串模板(JDK 22 预览 / JDK 23 第二预览 / JDK 24 第三预览)
    • Stream Gatherers(JDK 22 预览 / JDK 24 第二预览)
    • 隐式声明类与实例方法(JDK 23 预览 / JDK 24 第二预览)
    • 原始类型模式匹配(JDK 24 预览)
  • 附录

    • Java 核心知识点
    • Java SE 专业术语
    • Java特性索引(JDK 8 → 25)

变量概述

本章定位:理解Java变量的本质——内存中的一块命名存储空间。掌握标识符的命名规则与规范、变量的声明语法与作用域三大基石,以及常量的定义与使用。白歌说:"变量名是你写给人看的,编译器只看类型;常量和标识符规范是你写给自己看的,三个月后维护代码时你会感谢现在的自己。"


什么是变量

变量(Variable) 是内存中一块被命名的存储区域,用于存放特定类型的数据。Java是强类型语言,每个变量在声明时必须指定类型,且该类型在变量的整个生命周期中不可改变。

变量的三要素:

  1. 类型(Type):决定内存占用大小和数据范围
  2. 名称(Name):程序中对这块内存的标识符
  3. 值(Value):实际存储的数据

变量声明语法

声明形式语法格式示例
声明 + 赋值(两步)类型 变量名; → 变量名 = 值;int count; → count = 100;
声明并初始化(一步)类型 变量名 = 值;int count = 100;
多个同类型变量类型 变量1 = 值1, 变量2 = 值2;int a = 1, b = 2;
常量(不可变)final 类型 变量名 = 值;final double PI = 3.141592653589793;

完整示例

/**
 * 飞翔科技 - 变量声明演示
 * 场景:白歌教小崔规范地声明购物车变量
 */
public class VariableDeclaration {
    public static void main(String[] args) {
        // 方式一:先声明后赋值
        float price;
        price = 188.88f;
        
        // 方式二:声明并初始化(推荐)
        int quantity = 1000;
        
        // 方式三:多个同类型变量同时声明
        float discount = 88.8f, shippingFee = 8.8f;
        
        // 常量:使用 final 修饰
        final String SHOP_NAME = "飞翔小店";
        
        // 变量参与运算
        float totalAmount = price * 2 + shippingFee;
        
        System.out.println("【" + SHOP_NAME + "】");
        System.out.println("单价:¥" + price);
        System.out.println("库存:" + quantity + "件");
        System.out.println("折扣价:¥" + discount);
        System.out.println("运费:¥" + shippingFee);
        System.out.println("购买2件总金额:¥" + totalAmount);
    }
}
运行输出:
【飞翔小店】
单价:¥188.88
库存:1000件
折扣价:¥88.8
运费:¥8.8
购买2件总金额:¥386.56

标识符(Identifier)

标识符是程序员为类、方法、变量、常量等元素起的名字。在 Java 中,标识符不是随心所欲的——它必须遵循严格的命名规则,并鼓励遵守行业命名规范。

标识符命名规则(硬性规则,编译期检查)

规则正确示例错误示例错误原因
只能包含字母、数字、下划线_、美元符$basicSalary、orderIdbasic-Salary、中文名含非法字符 - 或非 ASCII 字符(允许但强烈不推荐)
不能以数字开头orderId20252025OrderId以数字开头
不能使用关键字/保留字myClassclass、int、ifclass、int、if 等是 Java 关键字
区分大小写price ≠ Price—price、Price、PRICE 是三个不同标识符
不能包含空格basicSalarybasic Salary含空格
长度无限制thisIsAVeryLongVariableName—理论上无上限,但建议适度

Java 关键字与保留字(53个)

Java 共有 53个关键字和保留字,这些单词不能用作标识符:

数据类型(8):byte short int long float double char boolean流程控制(10):if else switch case default for while do break continue修饰符(12):public protected private static final abstract synchronized transient volatile strictfp native default(接口默认方法,JDK 8+) 异常处理(6):try catch finally throw throws assert类与对象(10):class interface enum extends implements new this super instanceof package其他与保留字(7):return void import const(保留) goto(保留) _(JDK 9+ 关键字) var(JDK 10+ 局部变量类型推断) record(JDK 16+) sealed permits(JDK 17+)

📝 记忆技巧:IDE 通常会对关键字高亮显示,在 Eclipse/IntelliJ IDEA 中如果标识符变蓝/变紫,说明它可能是关键字。

标识符命名规范(软性规范,团队约定)

规范命名法适用场景示例
大驼峰(PascalCase)每个单词首字母大写类名、接口名、枚举名StudentService、OrderDao、HttpServletRequest
小驼峰(camelCase)首字母小写,后续单词首字母大写变量名、方法名、参数名basicSalary、orderId、getUserName()
全大写下划线(UPPER_SNAKE_CASE)全大写,单词间用下划线分隔常量(final 修饰的变量)MAX_VALUE、DEFAULT_PORT、PI
全小写点分隔全小写,层级用点分隔包名com.feixiangtech.order
见名知意避免单字母(循环变量除外)、不用拼音所有命名quantity 而非 q;price 而非 jiage
// ✅ 飞翔科技 — 标识符命名规范演示
public class StudentScoreCalculator {          // 类名:大驼峰
    public static final int MAX_SCORE = 100;    // 常量:全大写下划线
    private String studentName;                 // 变量名:小驼峰
    private int mathScore;                      // 变量名:小驼峰
    
    public int calculateTotalScore() {         // 方法名:小驼峰
        int totalScore = 0;                    // 局部变量:小驼峰
        return totalScore;
    }
}

命名规则

Java的标识符命名遵循以下规则。白歌在Code Review时最常抓的问题就是命名不规范。

硬性规则(编译期检查)

规则正确示例错误示例错误原因
只能包含字母、数字、下划线_、美元符$basicSalarybasic-Salary含非法字符-
不能以数字开头orderId20252025OrderId以数字开头
不能使用关键字/保留字myClassclassclass是关键字
区分大小写price ≠ Price——
不能包含空格basicSalarybasic Salary含空格

软性规范(团队约定)

规范说明示例
驼峰命名(camelCase)变量名/方法名,首字母小写basicSalary, orderId
帕斯卡命名(PascalCase)类名/接口名,首字母大写StudentService, OrderDao
全大写下划线常量MAX_VALUE, DEFAULT_PORT
见名知意避免单字母(循环变量除外)quantity 而非 q
不用拼音国际化与可读性price 而非 jiage

变量分类与作用域

作用域详细示例

/**
 * 飞翔科技 - 变量作用域演示
 * 场景:大翔要小崔理解工资计算中各变量的生命周期
 */
public class SalaryCalculator {
    // 实例变量:属于对象,有默认值
    String employeeName;          // 默认 null
    float basicSalary;            // 默认 0.0f
    
    // 静态变量:属于类,全局共享
    static String companyName = "飞翔科技";
    static final float TAX_RATE = 0.1f;  // 静态常量
    
    public void calculateSalary(float bonus) {
        // 局部变量:必须显式初始化
        float socialSecurity = 2320.00f;
        float personalTax = basicSalary * TAX_RATE;
        float actualSalary = basicSalary + bonus - socialSecurity - personalTax;
        
        // bonus 是方法参数,也是局部变量
        System.out.println("实发工资:¥" + actualSalary);
    }
    
    public static void main(String[] args) {
        SalaryCalculator sc = new SalaryCalculator();
        sc.employeeName = "大翔";
        sc.basicSalary = 8888.00f;
        sc.calculateSalary(18888.00f);  // 绩效奖金作为参数传入
        
        // 静态变量通过类名访问
        System.out.println("公司:" + SalaryCalculator.companyName);
    }
}
运行输出:
实发工资:¥24377.20
公司:飞翔科技

局部变量的"先声明后使用"陷阱

// ❌ 错误:局部变量未初始化就使用
public void wrongUsage() {
    int quantity;
    System.out.println(quantity);  // 编译错误:variable quantity might not have been initialized
}

// ✅ 正确:声明时初始化
public void correctUsage() {
    int quantity = 1000;
    System.out.println(quantity);  // 输出 1000
}

原理:实例变量和静态变量有JVM自动赋予的默认值(int默认为0,float默认为0.0f,boolean默认为false,引用类型默认为null),但局部变量存放在栈中,JVM不会自动初始化,编译器强制要求"先赋值后使用",以防止读取垃圾数据。


常量(Constant)

常量是用 final 关键字修饰的变量,一旦赋值后不可更改。常量的核心价值在于:避免魔术数字(Magic Number)、提高代码可读性和可维护性、编译器可进行内联优化。

常量的两种定义方式

类型语法特点示例
final 变量(运行时常量)final 类型 变量名 = 值;每个对象有一份副本,值在运行时确定final double pi = 3.141592653589793;
static final 变量(编译时常量)static final 类型 变量名 = 值;类级别共享,编译时确定值,编译器会直接内联到使用处static final int MAX_SIZE = 100;

编译时常量(Compile-Time Constant)

当 static final 修饰的变量满足以下条件时,称为编译时常量:

  1. 基本类型或 String 类型
  2. 声明时直接赋值(不是通过方法调用)
  3. 赋值表达式在编译期可确定
// ✅ 编译时常量:编译器可将 MAX_SIZE 直接内联为 100
public static final int MAX_SIZE = 100;

// ✅ 编译时常量:字符串拼接在编译期确定
public static final String FULL_NAME = "飞翔" + "科技";

// ❌ 不是编译时常量:new 运算符,值在运行时确定
public static final String CREATE_TIME = new String("2025-01-01");

// ❌ 不是编译时常量:方法调用,值在运行时确定
public static final long CURRENT_TIME = System.currentTimeMillis();

📌 编译时常量的优化:编译时常量会被直接替换为字面量内联到字节码中。如果你修改了一个编译时常量的值,所有引用该常量的类都必须重新编译,否则会继续使用旧值。这是 Java 中著名的"常量反模式"。

常量命名规范

规则示例
全大写字母MAX_VALUE 而非 maxValue
单词间用下划线分隔DEFAULT_PORT_NUMBER
含义明确SECONDS_PER_HOUR 而非 S
放置位置通常放在类的顶部(成员变量区域)

常量的意义(为什么用常量而不是直接写值?)

// ❌ 反例:魔术数字(Magic Number),难以理解和维护
if (userLevel > 3) {
    discount = price * 0.8;
}

// ✅ 正例:用常量替代,代码一目了然
public static final int VIP_LEVEL_THRESHOLD = 3;
public static final double VIP_DISCOUNT_RATE = 0.8;

if (userLevel > VIP_LEVEL_THRESHOLD) {
    discount = price * VIP_DISCOUNT_RATE;
}

常量的三大核心意义:

  1. 消除魔术数字:if (status == 2) 不如 if (status == ORDER_SHIPPED) 清晰
  2. 集中修改:折扣率从 0.8 改为 0.75 只需修改一处常量定义
  3. 编译器优化:编译时常量会被内联,性能无损

飞翔科技常量使用示例

/**
 * 飞翔科技 - 常量使用演示
 * 场景:飞翔商城的业务常量定义
 */
public class FeixiangConstants {
    // 编译时常量(static final)
    public static final String COMPANY_NAME = "飞翔科技";
    public static final int MAX_VIP_LEVEL = 5;
    public static final double TAX_RATE = 0.06;
    public static final int FREE_SHIPPING_THRESHOLD = 200;  // 满200免运费
    public static final String DEFAULT_CURRENCY = "CNY";
    
    // 运行时常量(final,每个实例可不同)
    private final String orderId;  // 构造函数中赋值,之后不可变
    
    public FeixiangConstants(String orderId) {
        this.orderId = orderId;  // 必须在构造函数中赋值
    }
    
    public static void main(String[] args) {
        // 通过类名访问静态常量
        System.out.println("欢迎来到" + COMPANY_NAME);
        System.out.println("税率:" + (TAX_RATE * 100) + "%");
        System.out.println("满" + FREE_SHIPPING_THRESHOLD + "元免运费");
        
        // final 局部变量
        final int buyCount = 3;
        // buyCount = 5;  // 编译错误!final变量不能重新赋值
        System.out.println("购买数量:" + buyCount + "件(不可更改)");
    }
}
运行输出:
欢迎来到飞翔科技
税率:6.0%
满200元免运费
购买数量:3件(不可更改)

面试考点

Q1:Java是强类型语言还是弱类型语言?

Java是强类型语言。每个变量在编译时就必须确定类型,且类型不可改变。这不同于JavaScript等弱类型语言,后者允许var x = 10; x = "hello";。Java的强类型特性使得编译器能在编译期捕获大量类型错误,提高程序健壮性。

Q2:局部变量和成员变量(实例变量)的默认值有何不同?

成员变量(实例变量和静态变量)有JVM自动赋予的默认值:整数类型为0,浮点类型为0.0,boolean为false,char为\u0000,引用类型为null。局部变量没有默认值,必须显式初始化后才能使用,否则编译报错。这是Java语言设计的安全机制:防止程序员读取栈上的随机数据。

Q3:final修饰的变量和普通变量有什么区别?

final修饰的变量只能赋值一次,赋值后不可更改。对于基本类型,值不可变;对于引用类型,引用(地址)不可变,但对象本身的内容可能可变。final常量通常使用全大写下划线命名(如MAX_SIZE),常用于定义配置常量、数学常量等。

Q4:变量名$price合法吗?_name合法吗?

$price合法,$是允许的字符(常用于编译器生成的代码)。_name在JDK 8中合法,但从JDK 9开始,单独的下划线_成为关键字,_name仍然合法。实际开发中不建议使用$或_开头,这通常是系统自动生成代码的命名惯例。

上一页
章节导读
下一页
常量概述