每天一分钟来一颗Java语法糖(一)语法糖介绍
Java语法糖介绍
语法糖简介
语法糖(Syntactic Sugar/SyntaxSugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin(彼得·兰丁) 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。语法糖就是对现有语法的一个封装。简而言之,语法糖让程序更加简洁,有更高的可读性。
维基百科介绍如下
In computer science, syntactic sugar is syntax within a programminglanguage that is designed to make things easier to read or to express。
语法糖好处
- 语法糖使得程序员更容易编写程序,更清晰准确表达业务逻辑。
- 不仅仅是语法的转换,还包括一些小的改进。
解语法糖
Java虚拟机并不支持语法糖。语法糖在编译阶段就会被还原成简单的基础语法结构,这个过程就是解语法糖。
Java中的语法糖只存在于编译期,在编译器将 .java 源文件编译成 .class 字节码时(javac命令)。
例如查看自动拆箱自动装箱的字节码,图片来自自动拆箱自动装箱
实际上源码还是简单的基础语法结构
如果查看com.sun.tools.javac.main.JavaCompiler的源码,就会发现在compile()中有一个步骤就是调用desugar(),这个方法就是负责解语法糖而实现的。
以下是来自笔者$JAVA_HOME/lib/tools.jar包内的com.sun.tools.javac.main.JavaCompiler类中的源码
public void compile(List<JavaFileObject> var1, List<String> var2, Iterable<? extends Processor> var3) {
if (var3 != null && var3.iterator().hasNext()) {
this.explicitAnnotationProcessingRequested = true;
}
if (this.hasBeenUsed) {
throw new AssertionError("attempt to reuse JavaCompiler");
} else {
this.hasBeenUsed = true;
this.options.put(Option.XLINT_CUSTOM.text + "-" + LintCategory.OPTIONS.option, "true");
this.options.remove(Option.XLINT_CUSTOM.text + LintCategory.OPTIONS.option);
this.start_msec = now();
try {
this.initProcessAnnotations(var3);
this.delegateCompiler = this.processAnnotations(this.enterTrees(this.stopIfError(CompileState.PARSE, this.parseFiles(var1))), var2);
this.delegateCompiler.compile2();
this.delegateCompiler.close();
this.elapsed_msec = this.delegateCompiler.elapsed_msec;
} catch (Abort var8) {
if (this.devVerbose) {
var8.printStackTrace(System.err);
}
} finally {
if (this.procEnvImpl != null) {
this.procEnvImpl.close();
}
}
}
}
private void compile2() {
try {
label44:
switch(2.$SwitchMap$com$sun$tools$javac$main$JavaCompiler$CompilePolicy[this.compilePolicy.ordinal()]) {
case 1:
this.attribute((Queue)this.todo);
break;
case 2:
this.flow(this.attribute((Queue)this.todo));
break;
case 3:
this.generate(this.desugar(this.flow(this.attribute((Queue)this.todo))));
break;
case 4:
Queue var1 = this.todo.groupByFile();
while(true) {
if (var1.isEmpty() || this.shouldStop(CompileState.ATTR)) {
break label44;
}
this.generate(this.desugar(this.flow(this.attribute((Queue)var1.remove()))));
}
case 5:
while(true) {
if (this.todo.isEmpty()) {
break label44;
}
this.generate(this.desugar(this.flow(this.attribute((Env)this.todo.remove()))));
}
default:
Assert.error("unknown compile policy");
}
} catch (Abort var2) {
if (this.devVerbose) {
var2.printStackTrace(System.err);
}
}
if (this.verbose) {
this.elapsed_msec = elapsed(this.start_msec);
this.log.printVerbose("total", new Object[]{Long.toString(this.elapsed_msec)});
}
this.reportDeferredDiagnostics();
if (!this.log.hasDiagnosticListener()) {
this.printCount("error", this.errorCount());
this.printCount("warn", this.warningCount());
}
}
public Queue<Pair<Env<AttrContext>, JCClassDecl>> desugar(Queue<Env<AttrContext>> var1) {
ListBuffer var2 = new ListBuffer();
Iterator var3 = var1.iterator();
while(var3.hasNext()) {
Env var4 = (Env)var3.next();
this.desugar(var4, var2);
}
return this.stopIfError(CompileState.FLOW, (Queue)var2);
}
protected void desugar(Env<AttrContext> var1, Queue<Pair<Env<AttrContext>, JCClassDecl>> var2) {
if (!this.shouldStop(CompileState.TRANSTYPES)) {
if (this.implicitSourcePolicy != ImplicitSourcePolicy.NONE || this.inputFiles.contains(var1.toplevel.sourcefile)) {
if (this.compileStates.isDone(var1, CompileState.LOWER)) {
var2.addAll((Collection)this.desugaredEnvs.get(var1));
} else {
1ScanNested var3 = new 1ScanNested(this, var1);
var3.scan(var1.tree);
Iterator var4 = var3.dependencies.iterator();
while(var4.hasNext()) {
Env var5 = (Env)var4.next();
if (!this.compileStates.isDone(var5, CompileState.FLOW)) {
this.desugaredEnvs.put(var5, this.desugar(this.flow(this.attribute(var5))));
}
}
if (!this.shouldStop(CompileState.TRANSTYPES)) {
if (this.verboseCompilePolicy) {
this.printNote("[desugar " + var1.enclClass.sym + "]");
}
JavaFileObject var13 = this.log.useSource(var1.enclClass.sym.sourcefile != null ? var1.enclClass.sym.sourcefile : var1.toplevel.sourcefile);
try {
JCTree var14 = var1.tree;
this.make.at(0);
TreeMaker var6 = this.make.forToplevel(var1.toplevel);
List var7;
if (!(var1.tree instanceof JCCompilationUnit)) {
JCClassDecl var15;
if (this.stubOutput) {
var15 = (JCClassDecl)var1.tree;
if (var14 instanceof JCClassDecl && this.rootClasses.contains((JCClassDecl)var14) && ((var15.mods.flags & 5L) != 0L || var15.sym.packge().getQualifiedName() == this.names.java_lang)) {
var2.add(new Pair(var1, this.removeMethodBodies(var15)));
}
return;
}
if (this.shouldStop(CompileState.TRANSTYPES)) {
return;
}
var1.tree = this.transTypes.translateTopLevelClass(var1.tree, var6);
this.compileStates.put(var1, CompileState.TRANSTYPES);
if (this.source.allowLambda() && var3.hasLambdas) {
if (this.shouldStop(CompileState.UNLAMBDA)) {
return;
}
var1.tree = LambdaToMethod.instance(this.context).translateTopLevelClass(var1, var1.tree, var6);
this.compileStates.put(var1, CompileState.UNLAMBDA);
}
if (this.shouldStop(CompileState.LOWER)) {
return;
}
if (this.sourceOutput) {
var15 = (JCClassDecl)var1.tree;
if (var14 instanceof JCClassDecl && this.rootClasses.contains((JCClassDecl)var14)) {
var2.add(new Pair(var1, var15));
}
return;
}
var7 = this.lower.translateTopLevelClass(var1, var1.tree, var6);
this.compileStates.put(var1, CompileState.LOWER);
if (this.shouldStop(CompileState.LOWER)) {
return;
}
for(List var8 = var7; var8.nonEmpty(); var8 = var8.tail) {
JCClassDecl var9 = (JCClassDecl)var8.head;
var2.add(new Pair(var1, var9));
}
return;
}
if (this.stubOutput || this.sourceOutput || this.printFlat) {
return;
}
if (!this.shouldStop(CompileState.LOWER)) {
var7 = this.lower.translateTopLevelClass(var1, var1.tree, var6);
if (var7.head != null) {
Assert.check(var7.tail.isEmpty());
var2.add(new Pair(var1, (JCClassDecl)var7.head));
}
return;
}
} finally {
this.log.useSource(var13);
}
}
}
}
}
}
Java 中最常用的语法糖主要有switch语句支持String与枚举、泛型和类型擦除、自动装箱与拆箱、方法边长参数、枚举、内部类、条件编译、断言、数值字面量、增强for循环、try-with-resources语句、Lambda表达式等。后续逐一详细介绍