0
点赞
收藏
分享

微信扫一扫

语法糖(1)

你的益达233 2022-01-16 阅读 138

语法糖
    其实就是指 java 编译器把 *.java 源码编译为 \*.class 字节码的过程中,**自动生成**和**转换**的一些代码,主要是为了减轻程序员的负担,算是 java 编译器给我们的一个额外福利。

默认构造函数
    java编译器帮我们加上的无参构造器,调用父类 Object 的无参构造方法
自动拆装箱 
    基本类型和其包装类型的相互转换过程,称为拆装箱
    在JDK 5以后,它们的转换可以在编译期自动完成
    Integer x = 1; =>//基本类型赋值给包装类型,称为装箱 Integer x = Integer.valueOf(1);
    int y = x;     =>//包装类型赋值给基本类型,称谓拆箱 int y = x.intValue();
泛型集合取值

    泛型也是在 JDK 5 开始加入的特性,但 java 在**编译泛型代码后**会执行 **泛型擦除** 的动作,即泛型信息在编译为字节码之后就**丢失**了,实际的类型都当做了 **Object** 类型来处理:
    所以调用get函数取值时,有一个类型转换的操作
    Integer x = (Integer) list.get(0);
    如果要将返回结果赋值给一个int类型的变量,则还有**自动拆箱**的操作
    int x = (Integer) list.get(0).intValue();Copy
可变参数
    可变参数 **String…** args 其实是一个 **String[]** args 
    如果未传递参数,等价代码为方法名(new String[]{}),**创建了一个空数组**,而不是直接传递的null
foreach
数组使用foreach编译器转换为fori循环
如果是集合使用foreach
集合要使用foreach,需要该集合类实现了Iterable接口,因为集合的遍历需要用到迭代器Iterator

switch字符串

   

public class Demo6 {
   public static void main(String[] args) {
      String str = "hello";
      switch (str) {
         case "hello" :
            System.out.println("h");
            break;
         case "world" :
            System.out.println("w");
            break;
         default:
            break;
      }
   }
}


在编译器中执行的操作   

public class Demo6 {
   public Demo6() {
      
   }
   public static void main(String[] args) {
      String str = "hello";
      int x = -1;
      //通过字符串的hashCode+value来判断是否匹配
      switch (str.hashCode()) {
         //hello的hashCode
         case 99162322 :
            //再次比较,因为字符串的hashCode有可能相等
            if(str.equals("hello")) {
               x = 0;
            }
            break;
         //world的hashCode
         case 11331880 :
            if(str.equals("world")) {
               x = 1;
            }
            break;
         default:
            break;
      }

      //用第二个switch在进行输出判断
      switch (x) {
         case 0:
            System.out.println("h");
            break;
         case 1:
            System.out.println("w");
            break;
         default:
            break;
      }
   }
}

过程说明:

- 在编译期间,单个的switch被分为了两个
  - 第一个用来匹配字符串,并给x赋值
    - 字符串的匹配用到了字符串的hashCode,还用到了equals方法
    - 使用hashCode是为了提高比较效率,使用equals是防止有hashCode冲突(如BM和C.)
  - 第二个用来根据x的值来决定输出语句
switch枚举
 

public class Demo7 {
   public static void main(String[] args) {
      SEX sex = SEX.MALE;
      switch (sex) {
         case MALE:
            System.out.println("man");
            break;
         case FEMALE:
            System.out.println("woman");
            break;
         default:
            break;
      }
   }
}

enum SEX {
   MALE, FEMALE;
}


 

编译器中执行的代码如下

public class Demo7 {
   /**     
    * 定义一个合成类(仅 jvm 使用,对我们不可见)     
    * 用来映射枚举的 ordinal 与数组元素的关系     
    * 枚举的 ordinal 表示枚举对象的序号,从 0 开始     
    * 即 MALE 的 ordinal()=0,FEMALE 的 ordinal()=1     
    */ 
   static class $MAP {
      //数组大小即为枚举元素个数,里面存放了case用于比较的数字
      static int[] map = new int[2];
      static {
         //ordinal即枚举元素对应所在的位置,MALE为0,FEMALE为1
         map[SEX.MALE.ordinal()] = 1;
         map[SEX.FEMALE.ordinal()] = 2;
      }
   }

   public static void main(String[] args) {
      SEX sex = SEX.MALE;
      //将对应位置枚举元素的值赋给x,用于case操作
      int x = $MAP.map[sex.ordinal()];
      switch (x) {
         case 1:
            System.out.println("man");
            break;
         case 2:
            System.out.println("woman");
            break;
         default:
            break;
      }
   }
}

枚举类

enum SEX {
   MALE, FEMALE;
}


 

转换后的代码

public final class Sex extends Enum<Sex> {   
   //对应枚举类中的元素
   public static final Sex MALE;    
   public static final Sex FEMALE;    
   private static final Sex[] $VALUES;
   
    static {       
        //调用构造函数,传入枚举元素的值及ordinal
        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);  
    } 
   
}

匿名内部类

public class Demo8 {
   public static void main(String[] args) {
      Runnable runnable = new Runnable() {
         @Override
         public void run() {
            System.out.println("running...");
         }
      };
   }
}

转换后的代码

public class Demo8 {
   public static void main(String[] args) {
      //用额外创建的类来创建匿名内部类对象
      Runnable runnable = new Demo8$1();
   }
}

//创建了一个额外的类,实现了Runnable接口
final class Demo8$1 implements Runnable {
   public Demo8$1() {}

   @Override
   public void run() {
      System.out.println("running...");
   }
}

如果匿名内部类中引用了局部变量

public class Demo8 {
   public static void main(String[] args) {
      int x = 1;
      Runnable runnable = new Runnable() {
         @Override
         public void run() {
            System.out.println(x);
         }
      };
   }
}


 

转化后代码

public class Demo8 {
   public static void main(String[] args) {
      int x = 1;
      Runnable runnable = new Runnable() {
         @Override
         public void run() {
            System.out.println(x);
         }
      };
   }
}

final class Demo8$1 implements Runnable {
   //多创建了一个变量
   int val$x;
   //变为了有参构造器
   public Demo8$1(int x) {
      this.val$x = x;
   }

   @Override
   public void run() {
      System.out.println(val$x);
   }
}


 


 

举报

相关推荐

Java语法糖

kotlin语法糖

Python语法糖大全

C#语法糖

js的语法糖

0 条评论