☰
Java基础语法必修:注释、关键字与字面量从入门到面试
2026/9/25 10:47:12 网站建设 项目流程

有次帮一位刚自学Java的朋友看代码,他把所有变量都命名为class、interface、public,然后问我为什么编译不过。我一看就明白了:他不是不会写代码,而是从来没认真吃过基础语法。这个场景估计很多人眼熟——网上到处是“快速入门 Java”的教程,却很少有人愿意停下来讲透注释、关键字、字面量这三样最不起眼的东西。本文就准备把这几块彻底掰开:注释怎么用才能不坑队友,编译器的关键字禁区到底在哪里,字面量背后又藏着多少面试题。如果你是刚接触Java基础语法的新手,或者准备面试时想把这些“八股”题答得干净利落,这篇内容都值得看完。

1. 注释不是写个说明那么简单:三种写法,三种用途

很多新手觉得注释是最没技术含量的部分,甚至有人觉得“代码能跑就行,写什么注释”。但等你真正进团队协作、接手别人的项目,或者三个月后回看自己写的代码,就知道注释写得好不好,直接决定你的代码是“资产”还是“负债”。Java里的注释一共三种:单行注释、多行注释、文档注释,每一种用途完全不同。

1.1 三种注释的语法边界与适用场景

单行注释是最常用的,用//开头,从//一直到本行末尾都会被编译器忽略。它适合给某一条语句做简短说明:

int count = 0; // 统计有效数据的数量

多行注释用/* ... */包起来,适合写一段逻辑说明、临时屏蔽某几行代码,或者写一段较长的设计备注:

/* * 这里处理数据校验: * 1. 为空直接返回 * 2. 长度超过32位截断处理 */

文档注释用/** ... */开头,结构上像多行注释,但它会被JDK自带的javadoc工具解析,直接生成一份HTML格式的API文档。注意,文档注释里可以写@param、@return、@throws这些标记,后面会细说。

三种注释有个最容易踩的坑:多行注释不能嵌套。比如下面这段代码是编译不过的:

/* 外层注释 /* 内层注释 */ */

原因很简单:编译器遇到第一个/*后会一直向后寻找第一个*/,根本不会认什么“内外层”,一旦嵌套,注释边界立刻乱套。很多人都在这儿翻过车,尤其是从Python或者其他语言转过来的,习惯性地认为注释可以随便套。

1.2 文档注释的正确打开方式

“文档注释以什么开头”这个问题,几乎是Java基础面试的送分题,答案就是/**。但真正能把文档注释用好的人不多。文档注释一般写在类、方法、成员变量前面,比如:

/** * 用户信息实体,对应 user 表 * * @author zhangsan * @since 1.0 */ public class User { /** * 用户ID,数据库自增主键 */ private Long id; /** * 根据ID查询用户 * * @param id 用户ID,不能为null * @return 查询到的用户信息,不存在时返回null * @throws IllegalArgumentException id为空时抛出 */ public User getUserById(Long id) { if (id == null) { throw new IllegalArgumentException("id不能为空"); } return null; } }

这里有个很实用的习惯:不要只在方法上有@param和@return,还要在方法描述里写清楚“什么时候会抛异常”“返回null代表什么”。很多线上事故就是因为调用方不知道方法会返回null,直接调用返回结果的字段导致空指针。文档注释写清楚,等于把你的代码意图公开告诉所有调用者。

在IDEA里,你可以把光标放在方法名上,按Alt + Enter,选择添加JavaDoc,IDEA会自动根据参数生成模板,你只需要补充描述。写完类和方法后,可以用javadoc -d doc 源文件.java命令生成API文档,也可以直接在IDEA的Tools -> Generate JavaDoc里操作。团队协作时,一份规范的API文档比口头交代可靠一百倍。

1.3 中文注释乱码:一个编码问题坑了无数新人

讲注释就绕不开编码。很多初学者第一次用命令行javac编译带中文注释的Java文件,报错或者生成乱码,一脸懵。原因很简单:你的源文件是UTF-8编码,而javac默认按平台字符集去读,Windows中文系统下默认是GBK,两边对不上就乱码了。

解决办法也很直接,编译时显式指定编码:

javac -encoding UTF-8 HelloWorld.java

如果用的是IDEA,新工程默认文件编码是UTF-8,一般不会遇到这个问题。容易出问题的是旧项目、从别处拷贝来的文件、或者多人协作时有人用记事本改过编码。所以建议在Maven的pom.xml里固定编译编码:

<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>

我见过有同学在MATLAB或者STM32开发环境里也被中文注释乱码折磨,其实本质上和Java是同一件事:编辑器按A编码读文件,文件却是B编码保存的。统一成UTF-8能解决绝大部分乱码问题。顺便说一句,如果数据库里存的中文也是乱码,先别再纠结Java代码了,去看JDBC连接的URL里有没有characterEncoding=utf8,以及数据库表、字段的字符集是否一致。编码问题是一个链条,任何一个环节不一致都会出乱码。

1.4 注释的“为什么”比“是什么”更值钱

市面上很多新手写的注释是这样的:

int a = 1; // 把1赋值给a

这种注释属于典型的“废话文学”,没写一样。真正值钱的注释是解释“为什么这么写”,因为“是什么”一看代码就懂,“为什么”才是当时决策的上下文。举个例子:

// 这里不能直接用 equals 判断,因为 historyList 可能达到百万级,直接比较会拖垮接口性能 if (historyList.size() != lastCount) { // 数据有变化,重新加载 }

这段注释把性能考量和判断依据写清楚了,后面接手的同事才敢放心改。再比如接第三方支付回调时,签名验证那段代码一定要注释“为什么先验签再处理业务”,否则以后有人为了“省一次查询”把顺序调整了,就会引入严重安全问题。

我自己给团队定的规矩是:注释只写三种内容——业务规则、边界条件、踩坑警告。代码本身能表达清楚的,不写注释;注释写不清楚的,先去重构代码。

2. 关键字:编译器给你划好的“禁区”,越线就报错

关键字是Java基础语法里最“硬”的一部分。它不是大家商量好的约定,而是编译器直接规定的词法规则:这些词已经被语言本身占用,你拿来做变量名、方法名、类名,编译直接报错。很多新手第一次被编译错误逼疯,往往就是因为踩了关键字的地雷。

2.1 关键字、保留字与特殊字面量:别把三件事混在一起

严格来说,Java里要区分三组概念:

  • 关键字:有明确语法含义的单词,比如class、if、for、new,必须小写,不能当标识符。
  • 保留字:当前版本还没用到,但为了向后兼容而预留的词,最典型的是goto和const。这两个词在Java里没有实际功能,但你不能拿它们做变量名。
  • 特殊字面量:true、false、null。严格讲它们不是关键字,是“字面量常量”,但也同样禁止用作标识符。

面试里经常有人被这句话绊倒:“true和false是不是Java关键字?”答案看你怎么定义。在Java语言规范里它们被定义为布尔类型的字面量,和int a = 1里的1地位一样。但因为它们也受标识符规则限制,很多面试题就直接把它们归进“不能用做标识符的单词”这一档。你答“它们是特殊布尔字面量,不能做标识符”既准确又显得你懂细节。

这里多说一句,C语言有32个关键字,常见的有auto、extern、register、const等。有人学完C再学Java,会下意识觉得extern、const在Java里也能用,结果被编译错误教做人。Java把const保留给未来版本,extern压根没有对应概念。不同语言的关键字名单差异很大,转语言时最好先把“禁用词表”过一遍。

2.2 47个关键字怎么记:按功能分类比死背高效

很多人背关键字表喜欢从abstract背到volatile,背完就忘。我的建议是按用途分组记忆,这样既好记,也能顺便理解Java的语法骨架。

分类关键字
类与对象class、interface、enum、extends、implements、new、this、super、instanceof
访问控制public、protected、private
基本类型byte、short、int、long、float、double、char、boolean、void
流程控制if、else、switch、case、default、for、while、do、break、continue、return
方法相关static、final、abstract、synchronized、native、strictfp
包相关package、import
异常处理try、catch、finally、throw、throws
其他transient、volatile、assert

这只是目前Java的标准关键字。注意,Java的关键字不是一成不变的,Java 10加入了var,Java 13加入了yield,Java 14加入了record,Java 17加入了sealed、permits。你现在去面试,如果只背老版本的47个词还不够,得知道新版本里哪些词变成了受限关键字或上下文关键字。

var是其中最典型的。Java 10开始支持局部变量类型推断,你可以写var list = new ArrayList<String>();,编译器会根据初始化表达式推断类型。但var不是传统意义上的关键字,它只在“能推断类型的位置”才有特殊含义,你仍然可以声明一个叫var的变量:

int var = 10; // 合法 var = 20; // 合法

这种“上下文关键字”的设计,是为了尽量少破坏已有代码。类似的还有yield,在Java 13之前它可以当变量名,之后在switch表达式中有了特殊作用,但作为变量名在非冲突场景下依然能用。如果你在一家公司维护老代码,看到这种语法要格外小心:新版本JDK可能让老代码里某些合法标识符变成编译错误。

2.3 static关键字:面试出场率最高的“关键字之王”

热搜词里“static关键字的作用”常年居高不下,因为它覆盖的知识面太宽了。一句话概括:static表示“属于类,而不是属于某个对象”。围绕这句话可以展开五个用法:

第一,静态变量(类变量)。所有对象共享同一份数据,内存里只有一份。比如public static int count = 0;,无论创建多少个对象,大家操作的都是同一个count。

第二,静态方法。可以直接通过类名调用,不需要先new对象。工具类里的方法基本都是静态的,比如Math.max、Integer.parseInt。静态方法里不能直接用this,因为this指向当前对象,而静态方法执行时可能根本没有对象。

第三,静态代码块。类加载时执行一次,适合做一次性的初始化操作,比如加载配置文件、初始化连接池。

public class Config { static { System.out.println("类加载时执行一次"); } }

第四,静态导入。import static java.lang.Math.max;之后可以直接写max(1,2),但这玩意儿用多了会让代码可读性变差,我不建议频繁使用。

第五,静态内部类。静态内部类不持有外部类对象的引用,创建时不需要先创建外部类。这在实现建造者模式、或者写一些与外部实例无关的辅助类时非常常用。

面试还有个经典连环问:main方法为什么必须是public static void main(String[] args)?拆开看:public是JVM在外部调用,必须公开;static是因为这时还不存在任何对象,JVM需要直接通过类名调;void因为main方法不需要返回值;参数String[] args用来接收命令行参数。你把这几句话说完,面试官就知道你对关键字有真实理解,而不是背概念。

2.4 “表中字段为关键字”的连锁反应:Java和数据库同理

搜索热词里有个很有意思的组合:“mysql表中字段为关键字”“gbase数据库修改字段注释”。这看起来和Java没关系,但底层是同一个易错点:关键字形成的标识符禁区,不只存在于编程语言里,也存在于SQL里。

比如你建表时心血来潮把某个字段命名为order、group、desc、key,建表可能报错,即使建表成功,后续SELECT也会因为语法歧义出问题:

-- 错误或需要转义 SELECT * FROM t_order WHERE desc = 'xxx'; -- 反引号包起来才能用 SELECT * FROM t_order WHERE `desc` = 'xxx';

Java这边更严格,关键字根本不能出现在标识符位置。所以当你看到一个编译错误“cannot find symbol”或者语法高亮里变量名变色了,第一反应应该检查:是不是用了class、static、new这些词当变量名。数据库字段命名遇到关键字,至少还能用反引号补救;Java标识符踩中关键字,除了改名没有第二条路。

所以我在项目里定了一个规矩:代码和数据库的命名都避开关键字和保留字。比如用户描述字段不叫desc而叫description,排序字段不叫order而叫sortNo。这样能省掉后续无数转义和排查工作。很多人以为规范命名是“讲究”,等他在线上真碰上一次desc字段引发的SQL异常,就会明白这条规矩是拿来救命的。

3. 字面量:代码里最诚实的数据,也是面试最爱挖的细节

字面量这个术语看起来很抽象,其实它指的就是在代码里直接写出来的“赤裸裸的值”。int a = 10;里的10是字面量,String name = "Tom";里的"Tom"也是字面量。理解字面量,是从“照着抄代码”到“真正理解内存里发生了什么”的关键一步。

3.1 六种字面量形态与默认类型

Java里的字面量按类型可以分成六组:

类型示例默认类型
整数100、-20、0xFFint
浮点数3.14、1e5double
字符'A'、'\n'char
字符串"hello"String
布尔true、falseboolean
空null任意引用类型

这里有个隐藏考点:整数字面量默认是int,浮点数字面量默认是double。所以下面这段代码是编译不过的:

long big = 3000000000L; // 需要加L或l,否则超出int范围 float pi = 3.14f; // 需要加F或f,否则默认double,大转小报错

不加后缀,编译器会按int和double去理解字面量。long类型的赋值能容纳更大数值,但字面量本身已经按int求值了,超范围就报错。float同理,3.14默认是double,直接塞给float会有精度风险,所以必须写3.14f。很多人第一次看到L、F后缀觉得多此一举,实际上这是你在告诉编译器“这个字面量到底是什么类型”。

3.2 进制、下划线、转义:容易被问倒的细节

Java里整数字面量除了十进制,还支持二进制、八进制、十六进制,并且可以在数字之间加下划线提升可读性:

表示方式前缀示例
二进制0bint x = 0b1101;
八进制0int x = 0127;
十六进制0xint x = 0xFF;
十进制无int x = 100;

如果你写int x = 010;,它的值不是10,而是八进制数10,也就是十进制8。这是一个古老的“陷阱”,很多从没接触过八进制表示法的新人都会在这里懵一下。下划线是Java 7之后引入的,1_000_000看起来比1000000清晰得多,但注意下划线不能放在数字开头、结尾或者小数点旁边:

int a = 1_000_000; // 合法,值为1000000 int b = _100; // 非法

字符字面量里的转义也常考,最常见的几个:

  • '\n'换行
  • '\t'制表符
  • '\\'反斜杠
  • '\''单引号
  • '\uXXXX'使用Unicode编码表示字符,比如'\u4e2d'代表“中”

这里有个小提醒:\uXXXX是编译器最早处理的转义之一,哪怕它出现在注释里都可能被解析。以前有个著名的坑,就是有人在注释里写了\u000d之类的内容,结果编译器把后面的代码“吞掉”了,非常诡异。所以看到字符转义相关的奇怪报错,先检查是不是Unicode转义惹的祸。

3.3 面试拼串题:1+2+"abc"背后是什么

网上流传很广的Java面试八股题里,有一道经典的字符串拼接题:

System.out.println(1 + 2 + "abc"); // 输出 3abc System.out.println("abc" + 1 + 2); // 输出 abc12

很多人只记住了结论,不理解原理。原理其实是Java运算符优先级和“从左到右结合”的规则:加号两边如果有一边是String,那整个+就变成字符串拼接操作,另一边会被转换成字符串;如果两边都是数字,那就正常做加法。

所以第一行先算1 + 2,两个都是int,结果是3,再和"abc"拼接成"3abc"。第二行从左到右先执行"abc" + 1,到这里已经有字符串了,结果是"abc1",再拼2得到"abc12"。理解了字面量的默认类型加运算顺序,这种题就不会靠死记硬背。

还有一个经常被拿来“钓鱼”的题:

System.out.println(null);

这行代码编译不过,因为System.out的println有多个重载,分别是String、char[]、Object等参数类型,null可以匹配多个,编译器无法确定调用哪一个。比单纯输出一个空值更有价值的是:这道题同时考了重载、null的字面量类型语义、以及“字面量本身没有对象类型,但会根据上下文确定类型”这个知识。

3.4 常量池和“==”边界:为什么面试官爱问127和128

字面量表面平凡,往深挖就涉及常量池。还记得Integer的缓存问题吗:

Integer a = 127; Integer b = 127; System.out.println(a == b); // true Integer c = 128; Integer d = 128; System.out.println(c == d); // false

原因在于:Integer字面量赋值时走的是自动装箱,Integer内部默认缓存了-128到127之间的Integer对象。a和b拿到的是同一个缓存对象,所以==比较地址时是true;超出缓存范围就各自创建新对象,==自然变成false。

字符串也一样:

String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2); // true,字符串常量池命中 String s3 = new String("abc"); System.out.println(s1 == s3); // false,一个是池里的对象,一个是堆上新对象

s1 == s2为true是因为字符串字面量会进入常量池,相同内容的字面量复用同一份对象。而new String("abc")强制在堆上新建一个对象,所以地址不同。这种题现在看起来有点“八股”,但它逼你理解:字面量不只是“写代码时看到的文本”,它关系到对象复用和内存布局,理解这一点对你日后排查内存问题、理解框架源码里的缓存设计都很有帮助。

4. 把注释、关键字、字面量拼进一个正经工程里

单独学每块内容都不难,真正难的是把它们揉进一段真实代码里,每一步都写对。这一章我们用一段最小但结构完整的Java类,把前面的知识全串一遍,然后聊聊工具链里的实操细节。

4.1 一个“五脏俱全”的最小类模板

下面这个类虽然不是业务系统代码,但它把注释的三种形态、关键字的典型使用、字面量的各类写法都包含了:

package com.example.demo; import java.time.LocalDate; /** * 学生信息工具类 * * @author coder * @version 1.0 */ public class Student { /** 默认年龄,用字面量赋值并加注释说明 */ private static final int DEFAULT_AGE = 18; private String name; private LocalDate birthday; static { System.out.println("Student 类正在加载"); } /** * 构造一个学生对象 * * @param name 学生姓名,不能为null或空字符串 */ public Student(String name) { if (name == null || name.isEmpty()) { throw new IllegalArgumentException("姓名不能为空"); } this.name = name; } // 打印基本信息,这个方法仅供演示 public void printInfo() { // 用加号拼接字符串,注意":"是字符串字面量 String info = "姓名:" + this.name + ",默认年龄:" + DEFAULT_AGE; System.out.println(info); } }

逐行看:package和import是包管理关键字;public、class、static、final、void、new、throw、this都是关键字;null是特殊字面量,配合==做判空;"姓名:"、18、"学生"都是不同类型的字面量;类和方法上面的/** ... */是文档注释,方法内部还用了单行注释。

这段代码我建议你亲手敲一遍,然后试着回答三个问题:如果去掉static,程序执行顺序会变吗?DEFAULT_AGE为什么必须加final?如果name为null,构造方法里为什么会先抛异常而不是等用到时再出错?这三个问题都能答上,说明你对关键字和字面量的理解已经到位了。

4.2 用javadoc把你的注释变成正式文档

很多新手写了/** */注释就完事了,完全不知道可以生成HTML文档。你可以把上面Student.java放在一个目录里,然后执行:

javadoc -d doc -encoding UTF-8 -charset UTF-8 Student.java

命令执行完,doc目录里会出现一个index.html,用浏览器打开,你会看到类名、方法签名、@param、@return全部被渲染成一份专业格式的API说明。这个过程会逼你重新审视自己的文档注释写得好不好——如果@param后面连参数含义都没写,生成的文档会很寒碜。

在IDEA里更简单:菜单栏Tools -> Generate JavaDoc,选择输出目录和Scope,点确定即可。团队协作时,最理想的流程是:代码里写规范文档注释,CI构建时自动生成API文档并发布到内网。这一步做起来,你的代码质量观会被拉高一个档次。

4.3 IDEA使用细节:快捷键与搜索关键字技巧

工欲善其事,必先利其器。初学者至少要知道这几个IDEA操作,它们能帮你快速定位“关键字踩坑”的问题。

注释快捷键是最基本的:单行注释Ctrl + /,多行注释Ctrl + Shift + /。IDEA还会在你输入/**后按回车自动补全文档注释模板,这个习惯从第一天就值得养成。

搜索文件里的关键字:单文件内用Ctrl + F,全局搜代码用Ctrl + Shift + F。当你怀疑哪个文件把Java关键字当变量名用了,全局搜class之类是很荒谬的,因为代码里到处是class关键字。更好的做法是先看语法高亮和编译Error列表,IDEA会直接把非法标识符标红,一般轮不到去搜索。

搜依赖Jar包里的内容:有人问“IDEA怎么搜索jar包中的关键字”,其实很简单:双击Shift打开全局搜索,切到All Places选项卡,就能搜到当前项目依赖的jar包里的类名、方法名,甚至源码里的字符串。比如你想确认某个jar包是否用了Java 17的新特性,可以直接搜sealed、record这些关键字,能搜到说明该jar包含相关代码。这个技巧在排查“某个依赖是否有问题版本”的时候特别管用。

4.4 新手自查清单:写完后记得对一遍

学了这么多,最后给你一份可以直接对照的自查清单。每次写完一个小程序,花30秒扫一遍,能减少大量低级错误:

检查项是否正确
标识符是否踩中关键字或保留字是 / 否
类名、方法名是否用了驼峰命名是 / 否
常量是否用static final修饰是 / 否
long和float字面量是否加了L、F后缀是 / 否
中文注释没有乱码,文件编码为UTF-8是 / 否
文档注释是否写了@param、@return是 / 否
字符串拼接顺序和类型是否符合预期是 / 否
判空是否用了null字面量配合==是 / 否

这条清单里的每一条,背后都是有人在线下栽过跟头的。尤其“标识符踩中关键字”这一条,我见过不下五次,连工作三五年的老手偶尔也会写出case结尾的字段,然后被SQL或Java编译问题折腾半天。

我个人在实际教学和带新人时,最深的体会是:基础语法从来不是“智商税”,而是未来所有高级特性的地基。注释、关键字、字面量这三样东西,你越早把它们理清楚,后面学集合、泛型、并发时就越省力。很多人在Spring Boot里被各种魔法注解弄得晕头转向,回头发现根本没搞懂普通interface和@interface的区别;还有人调试空指针调半天,回来才发现自己对null这个字面量的理解只停留在拼写上。这篇内容把最基础的几块掰开揉碎讲完,自己也顺手把过往踩过的坑重新沉淀了一遍。如果你正在入门Java,别急着刷Spring、微服务,先把本地的javac、java命令玩明白,把这些基础语法的“禁区”和“字面量性格”摸清楚,后面的路会顺很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询