编译器的语法糖

编译器处理:

​ 语法糖:就是编译器把.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:{
              
          }
      }
      
    • 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);
    }
    
posted @ 2025-03-19 11:29  烟雨断桥  阅读(7)  评论(0)    收藏  举报