编译器处理:
语法糖:就是编译器把.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(){@Overridepublic 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); }