ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Java基础语法必修:注释、关键字与字面量从入门到面试

Java基础语法必修:注释、关键字与字面量从入门到面试 有次帮一位刚自学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选择添加JavaDocIDEA会自动根据参数生成模板你只需要补充描述。写完类和方法后可以用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.sourceEncodingUTF-8/project.build.sourceEncoding /properties我见过有同学在MATLAB或者STM32开发环境里也被中文注释乱码折磨其实本质上和Java是同一件事编辑器按A编码读文件文件却是B编码保存的。统一成UTF-8能解决绝大部分乱码问题。顺便说一句如果数据库里存的中文也是乱码先别再纠结Java代码了去看JDBC连接的URL里有没有characterEncodingutf8以及数据库表、字段的字符集是否一致。编码问题是一个链条任何一个环节不一致都会出乱码。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加入了varJava 13加入了yieldJava 14加入了recordJava 17加入了sealed、permits。你现在去面试如果只背老版本的47个词还不够得知道新版本里哪些词变成了受限关键字或上下文关键字。var是其中最典型的。Java 10开始支持局部变量类型推断你可以写var list new ArrayListString();编译器会根据初始化表达式推断类型。但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、\nchar字符串helloString布尔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 面试拼串题12abc背后是什么网上流传很广的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命令玩明白把这些基础语法的“禁区”和“字面量性格”摸清楚后面的路会顺很多。
返回列表