编译器的语法糖
编译器处理:
语法糖:就是编译器把.java源码,编译为.class字节码的过程中,自动生成和转换的一些代码【减轻程序员的负担】。
-
默认构造器【无参】:
public class Cat{ } // => public class Cat { public Cat(){ super(); } } -
自动拆装箱:
- 值在[-128, 127]会重缓冲区取值,不会new一个对象【Integer类维护了一个缓冲区】;
{ Integer x = 1; int y = x; } //=> { Integer x = Integer.valueOf(1); int y = x.intValue(); } -
泛型集合取值:
-
java在编译泛型代码后会执行泛型擦除的动作,即泛型信息在编译为字节码阶段后,就丢失了。实际的类型都当作了Object类型来处理【但在取出操作时,字节码会多一个强制类型转换操作】;
List<Integer> list = new ArrayList<>(); list.add(10); Integer x = list.get(0); //=> Integer x = (Integer)list.get(0); -
泛型擦除,擦除的字节码上的泛型信息,但是可以又LocalVariableTypeTable仍然保留了泛型信息;
-
使用反射获取不到局部变量的泛型信息,仅仅可以获取方法参数和返回值的泛型信息;
-
-
可变参数:
- 当传入无参的时候,会传入一个空的数组,而不会传入一个null【new String[]{},为了避免空指针异常】;
String... args; //=> String[] args; -
foreach循环
-
foreach和数组的配合使用,是使用下标取值;
int[] array = {1, 2, 3, 4}; for (int e : array) { System.out.print(e); } // => int[] array = new int[]{1, 2, 3, 4}; for (int i=0; i<array,length; i++) { int e = array[i]; System.out.print(e); } -
foreach和集合【Set,没有下标】的配合使用,是使用迭代器;
List<Integer> list = Array.asList(1, 2, 3); for (Integer e : list) { System.out.print(e); } // => List<Integer> list = Array.asList(1, 2, 3); Iterator iter = list.iterator(); while (iter.hasNext()){ Integer e = (Integer)iter.next(); System.out.print(e); }
-
-
switch匹配
-
jdk7开始,switch才可以作用于字符串和枚举类【对应变量不能用空】;
-
String:一个switch匹配会产生两个switch;
- 引入一个byte变量,通过第一个switch确定变量的值【通过,hasCode和equals方法已经比较】;
- hasCode()是为了提高效率;
- equals()是为了防止hash冲突;
- 第二个switch通过byte变量值,选择具体应该执行的代码块;
switch(str) { case "hello": { } case "world": { } } //=> byte x = -1; switch(str.hasCode()){ case "hello".hasCode(): { if(str.equals("hello")){ x = 0; } break; } case "world".hasCode(): { if (str.equals("world")) { x = 1; } break; } } switch(x) { case 0:{ } case 1:{ } } - 引入一个byte变量,通过第一个switch确定变量的值【通过,hasCode和equals方法已经比较】;
-
enum:枚举类的switch匹配
- 会在对应位置定义一个静态合成类【未命名】,因此仅jvm可见,
- 通过枚举的ordinal()的值,和数组进行映射;
enum Sex { MALE, FEMALE; } switch(sex) { case MALE:{ } case FEMALE:{ } } // => static class $MAP{ static in[] map = new int[2]; static { map[Sex.MALE.ordinal] = 1; map[Sex.MALE.ordinal] = 2; } } int x = $MAP.map(sex.ordinal()); switch(x) { case 1:{ } case 2:{ } }
-
-
枚举类:
enum Sex{ MELE, FEMMALW; } //=> public final class Sex extends Enum<Sex> { public static final Sex MALE; public static fianl Sex FEMALE; private static final Sex[] $VALUES; static { MALE = new Sex("MALE", 0); FEMALE = new Sex("FEMALE", 1); $VALUES = new Sex[]{MALE, FEMALE}; } private Sex(String name, int ordinal) { super(name, ordinal); } public static Sex[] values(){ return $VALUES.clone(); } public static Sex valueOf(String name) { return Enum.valueOf(Sex.class, name); } } -
try-with-resources
-
jdk7开始新增了对关闭资源处理的特殊语法;
-
资源对象需要实现 AutoClaseable接口;
-
可以同时保留资源操作异常和资源关闭异常;
try(资源变量 = 创建资源对象){ } catch(){ } //相当于python的with,自动关闭; //eg: try(InputStream is = new FileInputStream(file)) { System.out.println(is); }catch(Exception e) { e.printStackTrace(); } // => try{ InputStream is = new FileInputStream(file); Throwable t = null; //增加临时局部变量,为了后续判断; try { System.out.println(is); }catch (Throwable e1) { //try{}的资源处理代码块出现异常; t = e1; throw e1; }finally{ if (is != null) { // 为null,不用释放资源 if (t != null) { // 资源处理代码块出现异常,此时至少有一个异常; try{ is.close(); }catch (Throwable e2) { //保留资源操作异常和资源关闭异常,最后通过throw e1抛出,e1和t是同一个对象; t.addSuppressed(e2); } }else { is.close; //资源处理代码块出现没有异常时,当关闭资源出现异常时,会被Exception捕获【仅仅一个异常】 } } } }catch(Exception e){ //这部分没变; e.printStackTrace(); }
-
-
方法重写时的桥接方法:
-
方法重写时候的返回值分两种情况:
-
子类父类的返回值相同;
-
子类的返回值是父类返回值的子类;
- synthetic bridge方法仅虚拟机可见,并且没有命名冲突,可以通过反射验证;
//父类方法 public Number m(){ return 1; } //子类方法 @OVerrider public Integer m(){ return 2; } // 编译器=> public Integer m(){ return 2; } // 这个方法才是正真重写了父类 pblic Number m()方法; public systhetic bridge Number m(){ return m(); }
-
-
-
匿名类内部类
- 匿名内部类会被编译器创建类;
- 因此也解释了匿名内部类引用局部变量时,局部变量必须时final的,因为一旦创建,内部类的变量和外部类的变量就是两个变量,只是值相同;
class A { final int x = 10; Runnable runnable = new Runnable(){ @Override public void run(){ System,out.println(x); } } } //=> final class A$1 implements Runnable { int val$x; A$1(int x) { this.val$x = x; } public void run() { System.out.println(this.val$x); } } public class A{ final int x = 10; Runnable runnable = new A$1(x); }

浙公网安备 33010602011771号