Java 标识符、关键字与命名规范

语法规则决定"能不能编译通过",命名规范决定"能不能长期维护"。


一、什么是标识符(Identifier)

标识符就是程序员在编写代码时,为变量、方法、类、接口、包、常量、参数、枚举、注解等程序元素所起的名字。

凡是需要"起名字"的地方,都叫标识符。例如:

public class HelloWorld {          // HelloWorld 是类名(标识符)
    public static void main(String[] args) {   // main / args 是标识符
        int studentCount = 10;     // studentCount 是变量名(标识符)
        String name = "Java";      // name 是变量名(标识符)
        printMessage(name);        // printMessage 是方法名(标识符)
    }

    static void printMessage(String msg) { ... }
}

重要区分:关键字(keyword)、保留字(reserved word)、字面量(literal)不能作为标识符使用,它们是 Java 语言自己占用的名字。详见下文规则 3。


二、定义标识符的规则(语法规则,必须遵守)

这些是编译器的硬性规定,违反会直接编译报错。共有 4 条核心规则:

规则 1:组成字符限制

标识符只能由以下字符组成:

允许 说明 示例
字母 A-Z / a-z 26 个英文字母(大小写敏感) name, Age
数字 0-9 不能作为开头字符 count2, user1
下划线 _ 可作开头(JDK 9 后单独使用 _ 被禁止) _temp, max_value
美元符号 $ 合法但不推荐(编译器/框架常用) $value
Unicode 字符 Java 支持中文等 Unicode 字符 姓名, 学生
int 年龄 = 20;     // ✅ 合法(Unicode 支持),但工程中不推荐
int $price = 100;  // ✅ 合法,但不推荐
int _ = 10;        // ❌ JDK 9 起,单独的下划线被正式保留,禁止作为标识符
int user-name = 1; // ❌ 连字符 - 非法

规则 2:不能以数字开头

int 1num = 10;   // ❌ 编译报错:不能以数字开头
int num1 = 10;   // ✅ 正确
int _1num = 10;  // ✅ 正确(数字前有其他字符即可)

规则 3:不能使用关键字、保留字和字面量

Java 共有 50 个关键字(其中 2 个"保留但从未使用")、3 个字面量(常被误认为关键字),外加 Java 10+ 引入的一批上下文关键字。权威出处是 JLS(Java 语言规范)§3.9。

3.1 先分清几个概念

概念 定义 能否用作标识符 例子
标识符 程序员给类、方法、变量起的名字 —— Person、name、main
关键字 语言预定义、已被语法"征用"的词 ❌ 不能 class、if、int
保留字 为将来扩展预留、当前语法未启用的词 ❌ 不能 const、goto
字面量 代码里直接写出的"值" ❌ 不能 123、"abc"、true、null
上下文关键字 只在特定语境中才有关键字含义的词 ✅ 其他语境可以 var、record、sealed

"能否用作标识符"的意思是:这个词还能不能拿来给你的类、方法、变量起名字。

int age = 1;      // ✅ age 是普通词,可以起名
int class = 1;    // ❌ class 是关键字,已被语法占用
int const = 1;    // ❌ const 是保留字,已被预定
int true = 1;     // ❌ true 是字面量
String var = "x"; // ✅ var 是上下文关键字,这里可以(但不推荐)

关键字(Keyword)

  • 语言预定义的、有固定语法含义的词,编译器直接按语法规则解释。
  • 已被语法"征用",含义固定(class 声明类、if 条件判断)。
  • 不能用作标识符;全部小写;IDE 中通常高亮显示。

保留字(Reserved Word)

  • 为将来语法扩展预留的词——当前没有任何语法含义,但禁止程序员使用。
  • Java 只有 2 个:const、goto,相当于关键字的"候选池"。

两者关系一句话概括:被语法启用的保留词,就是关键字。const / goto 进了"候选池"却从没上岗——它们名字列在 JLS 的 50 个关键字清单里(所以总数是 50),但语法中查无此词,属于"名存实亡"的成员。

字面量(Literal)

  • 代码中直接写出的值本身,如 123、"abc"、true、null。
  • 它不是语法结构词,但因为同样不能作标识符,常被误认成关键字。

上下文关键字(Contextual Keyword)

  • Java 10+ 的折中设计——只在特定语法位置才被解释为关键字,其他位置仍可当普通标识符用,保证旧代码不被破坏。

3.2 50 个关键字(按用途分类)

分类 数量 关键字
访问控制 3 private protected public
声明与修饰符 14 abstract class enum extends final implements interface native new static strictfp synchronized transient volatile
程序控制 13 assert break case continue default do else for if instanceof return switch while
异常处理 5 catch finally throw throws try
包相关 2 import package
基本类型 8 byte short int long float double char boolean
引用与返回 3 this super void
保留字 2 const goto

3.3 3 个字面量(不是关键字!)

字面量 含义 示例
true boolean 类型的真值 boolean ok = true;
false boolean 类型的假值 boolean ok = false;
null 引用类型的空值,表示"不指向任何对象" String s = null;

为什么容易被误认为关键字:它们不能用作标识符(int true = 1; 编译报错),行为和关键字一样;IDE 里同样有高亮显示;有些教材把它们算进关键字,得出"Java 有 53 个关键字"的说法——严格按 JLS,它们是字面量,和 123、"abc" 一样是"值"。

3.4 上下文关键字与受限关键字

Java 10+ 引入的上下文关键字(Contextual Keyword),只在特定语境中才有关键字含义,其余地方仍可当标识符用(为兼容旧代码):

关键字 引入版本 生效语境
var Java 10 局部变量类型推断(实际是"受限类型名" reserved type name)
record Java 16 记录类声明
sealed Java 17 密封类/接口声明
permits Java 17 sealed 的许可子类列表
non-sealed Java 17 解除密封
yield Java 14 switch 表达式中返回值

注意:var 严格说是"受限类型名"(reserved type name),只用于局部变量类型推断,不能用于字段、方法参数、返回类型。

模块系统(Java 9)还有一批受限关键字,只在 module-info.java 里生效:

module requires exports opens to uses provides with open transitive

3.5 关键字/保留字示例

int class = 10;     // ❌ class 是关键字
int goto = 20;      // ❌ goto 是保留字
int Class = 10;     // ✅ 合法(Class 大写,Java 大小写敏感)
int classRoom = 5;  // ✅ 合法(整体不是关键字)

规则 4:大小写敏感,长度无限制

  • Java 严格区分大小写:Name 和 name 是两个不同的标识符。
  • 长度无理论上限(但工程上不要过长,见命名规范)。
int age = 18;
int Age = 20;   // ✅ 与 age 是两个不同变量,合法但极易混淆,禁止这样写

小结记忆口诀:标识符 = 字母/下划线/美元符开头 + 数字/字母/下划线/美元符 + 非关键字/保留字/字面量。


三、容易踩的坑

  1. const 和 goto 是保留字——从 C++ 沿袭的语法槽位,Java 从未启用,也不允许你定义名为 const 的变量。
  2. var 不是关键字(Java 10+)——它是"受限类型名"(reserved type name),只能用于局部变量类型推断。
  3. 上下文关键字(Java 14–17+)——只在特定语境中才有关键字含义,其余地方仍可当标识符用(为了兼容旧代码)。
  4. _ 下划线:Java 9 起单独的下划线被正式保留,不能作标识符——Oracle 为未来的语法特性占的坑。
  5. 模块系统(Java 9)的受限关键字 module requires exports opens to uses provides with open transitive——只在 module-info.java 里生效。
  6. strictfp 从 Java 17 起语义上已废弃(JEP 306:浮点运算默认严格),但关键字本身仍保留。

四、Java 名称命名规范(约定俗成,工程必遵守)

语法规则只保证"能编译",命名规范保证"能读懂、能协作"。规范不是编译器强制的,但违反会降低代码可读性、触发 Code Review 被退回、违反阿里/Google 等编码规约。

4.1 总体原则(阿里 Java 开发手册核心)

  1. 见名知意:名字必须表达实际含义,杜绝无意义命名。
  2. 规范统一:同一个项目、同一类元素使用统一风格。
  3. 全英文命名:禁止拼音、拼音+英文混用(如 shuJu)。
  4. 缩写谨慎:除公认缩写(id、url、http、api、dao、vo)外,不随意缩写。

4.2 各类元素的命名规范(核心对照表)

元素类型 命名风格 示例 错误示例
包名 全小写,点分隔,一般用域名倒写 com.alibaba.fastjson com.Alibaba
类名 / 接口名 大驼峰 PascalCase(首字母大写) UserService、HttpClient userService
方法名 小驼峰 camelCase(动词/动词短语开头) getUserName()、saveOrder() GetUserName
变量名 小驼峰(名词) userName、orderTotal UserName
常量名 全大写 + 下划线分隔 MAX_COUNT、DEFAULT_SIZE maxCount
参数名 小驼峰(与变量一致) userId、pageSize UserID
枚举类名 大驼峰;枚举值全大写+下划线 Color.RED、Status.PROCESSING Color.red
泛型参数 单个大写字母 <T>、<E>、<K,V> <Type>
测试类 被测类名 + Test 后缀 UserServiceTest TestUserService

4.3 驼峰命名法详解

// 大驼峰(PascalCase):每个单词首字母大写 —— 用于类名、接口名
public class OrderServiceImpl implements OrderService { }

// 小驼峰(camelCase):首单词小写,其余单词首字母大写 —— 用于方法、变量
private int orderTotalCount;
public String getUserName() { return null; }

// 全大写 + 下划线(UPPER_SNAKE_CASE)—— 用于常量
public static final int MAX_RETRY_TIMES = 3;

4.4 布尔类型变量命名(阿里规约强制)

布尔类型变量,不要加 is 前缀,否则部分框架序列化会出问题:

boolean success = true;     // ✅ 正确
boolean isSuccess = true;   // ❌ 错误,禁止 is 前缀

// 但 POJO 类中的布尔字段对应 getter 用 isXxx(框架规范)
private boolean deleted;
public boolean isDeleted() { return deleted; }  // ✅ getter 允许 is

4.5 分层/场景命名约定(大厂常见)

场景 约定 示例
Service 层接口 XxxService UserService
Service 实现 XxxServiceImpl UserServiceImpl
DAO/Mapper 层 XxxDao / XxxMapper UserDao、UserMapper
实体类 XxxDO / XxxPO / XxxEntity UserDO、UserPO
数据传输对象 XxxDTO / XxxVO / XxxBO UserDTO、UserVO
工具类 XxxUtils / XxxUtil StringUtils、DateUtil
常量类 XxxConstants RedisKeyConstants
异常类 XxxException BusinessException
配置类 XxxConfig / XxxProperties RedisConfig

4.6 命名反例与正例对照

// ❌ 反例
int a = 1;                    // 无意义
String s;                     // 无意义
int shuJu = 10;               // 拼音
String user_name = "tom";     // 变量用了下划线风格(应为 camelCase)
class USER { }                // 类名全大写
public static final int MaxCount = 3;  // 常量未全大写

// ✅ 正例
int studentAge = 18;
String studentName;
int dataCount = 10;
String userName = "tom";
class User { }
public static final int MAX_COUNT = 3;

五、总结

1. 先有概念,再看清单:关键字 = 被语法启用的保留词;保留字 = 预留未启用的词(const、goto);字面量 = 值;上下文关键字 = 特定语境才生效。

2. 记住三层结构:50 关键字 + 3 字面量 + 上下文关键字。

  • 50 个关键字分八大类:访问控制、声明与修饰符、程序控制、异常处理、包相关、基本类型、引用与返回、保留字。
  • 2 个保留字(const、goto)从未启用,仅占语法槽位。
  • 3 个字面量(true/false/null)不是关键字,但同样不能作标识符。
  • 上下文关键字(var、record、sealed、permits、non-sealed、yield)是 Java 10+ 的现代化设计。

3. 语法规则 vs 命名规范对比:

维度 语法规则(硬性) 命名规范(软性)
是否强制 编译器强制,违反报错 团队约定,违反不报错
关注点 能否编译通过 能否读懂、维护
约束来源 Java 语言规范(JLS) 阿里规约 / Google Style / 团队规范
典型条款 不能以数字开头、不能用关键字 驼峰命名、见名知意、不用拼音

一句话总结:语法规则决定下限,命名规范决定上限。 前者是 Java 的准入证,后者是成为一名合格工程师(尤其大厂工程师)的基本功。日常写代码不必死记——IDE 高亮会帮你内化,但分类表让你"按功能检索",坑点清单让你避开误区。


posted @ 2026-08-15 23:21  HuangBingQuan  阅读(9)  评论(0)    收藏  举报