JAVA语法糖原理你知道吗

目录
  • Java语法糖
  • 1.基本概念
    • 1.1语法糖
    • 1.2解语法糖
  • 2.常见糖块
    • 2.1 switch 支持 String 与枚举
    • 2.2泛型
    • 2.3自动装箱与拆箱
    • 2.4方法变长参数
    • 2.5枚举
    • 2.6条件编译
    • 2.7 for : each循环
  • 3.最后
    • 3.1Java编译与反编译
  • 总结

Java语法糖

​ 几乎所有的编程语言都或多或少提供过一些语法糖来方便程序员的代码开发,这些语法糖虽然不会提供实质性的功能改进,但是它们或能提高效率,或能提升语法的严谨性,或能减少编码出错的机会。

1.基本概念

1.1语法糖

​ 语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。简而言之,语法糖让程序更加简洁,有更高的可读性。

1.2解语法糖

解语法糖

​前面提到过,语法糖的存在主要是方便开发人员使用。但其实,Java虚拟机并不支持这些语法糖。这些语法糖在编译阶段就会被还原成简单的基础语法结构,这个过程就是解语法糖。Java语言中,javac命令可以将后缀名为.java的源文件编译为后缀名为.class的可以运行于Java虚拟机的字节码。

​ 如果你去看com.sun.tools.javac.main.JavaCompiler的源码,你会发现在compile()中有一个步骤就是调用desugar(),这个方法就是负责解语法糖的实现的。

~~此处需要javac的源码

2.常见糖块

2.1 switch 支持 String 与枚举

​ 都知道,Java中的swith自身原本就支持基本类型。比如int、char等。对于int类型,直接进行数值的比较。对于char类型则是比较其ascii码。所以,对于编译器来说,switch中其实只能使用整型,任何类型的比较都要转换成整型。比如byte。short,char(ackii码是整型)以及int。

演示代码:

public static void main(String[] args) {

    }
//    @Test
    public void Test1(){
//        Scanner scanner=new Scanner(System.in);
//        String next = scanner.next();
        String next="小高";
        switch (next){
            case "小高":
                System.out.println("我是小高");
                break;
            case "大高":
                System.out.println("我最美");
                break;
        }
    }

解释:

2.2泛型

​ 通常情况下,一个编译器处理泛型有两种方式:Code specialization和Code sharing。C++和C#是使用Code specialization的处理机制,而Java使用的是Code sharing的机制。

2.3自动装箱与拆箱

​ 自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。

演示代码:

public static void main(String[] args) {
        Integer a=1;//自动装箱
        int b=a;//自动拆箱
    }

解析:

可以看到,自动拆箱与装箱分别封装了Integer中的intValue()与valueOf()方法。

2.4方法变长参数

​ 可变参数(variable arguments)是在Java 1.5中引入的一个特性。它允许一个方法把任意数量的值作为参数。常见的就是printf()方法。

 public static void main(String[] args)
    {
        print("高冷", "公众号:高冷小伙", "博客:高冷小伙");
    }

    public static void print(String... strs)
    {
        for (int i = 0; i < strs.length; i++)
        {
            System.out.println(strs[i]);
        }
    }

从反编译后代码可以看出,可变参数在被使用的时候,他首先会创建一个数组,数组的长度就是调用该方法是传递的实参的个数,然后再把参数值全部放到这个数组当中,然后再把这个数组作为参数传递到被调用的方法中。

**注:**String…是java5新加入的功能,表示的是一个可变长度的参数列表。

2.5枚举

​ Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割。例如定义一个颜色的枚举类。

演示代码:

public enum t {
    SPRING,SUMMER;
}

反编译后的代码:

public final class T extends Enum
{
    private T(String s, int i)
    {
        super(s, i);
    }
    public static T[] values()
    {
        T at[];
        int i;
        T at1[];
        System.arraycopy(at = ENUM$VALUES, 0, at1 = new T[i = at.length], 0, i);
        return at1;
    } 

    public static T valueOf(String s)
    {
        return (T)Enum.valueOf(demo/T, s);
    } 

    public static final T SPRING;
    public static final T SUMMER;
    private static final T ENUM$VALUES[];
    static
    {
        SPRING = new T("SPRING", 0);
        SUMMER = new T("SUMMER", 1);
        ENUM$VALUES = (new T[] {
            SPRING, SUMMER
        });
    }
}

通过反编译后代码我们可以看到,public final class T extends Enum,说明,该类是继承了Enum类的,同时final关键字告诉我们,这个类也是不能被继承的。

当我们使用enmu来定义一个枚举类型的时候,编译器会自动帮我们创建一个final类型的类继承Enum类,所以枚举类型不能被继承。

2.6条件编译

​ Java语法的条件编译,是通过判断条件为常量的if语句实现的。根据if判断条件的真假,编译器直接把分支为false的代码块消除。通过该方式实现的条件编译,必须在方法体内实现,而无法在正整个Java类的结构或者类的属性上进行条件编译。

2.7 for : each循环

for:each循环比for循环的代码量要少很多,但实际上就是使用了For循环和迭代器。

演示代码:

 public static void main(String[] args) {
        String[] strs={"高效","高冷","高超","高速"};
        for(String str:strs){
            System.out.println(str);
        }
    }

解析:

public static void main(String[] args) {
    String[] strs = new String[]{"高效", "高冷", "高超", "高速"};
    String[] var2 = strs;
    int var3 = strs.length;

    for(int var4 = 0; var4 < var3; ++var4) {
        String str = var2[var4];
        System.out.println(str);
    }

}

3.最后

3.1Java编译与反编译

java cp D:\JVM_Study\src\SyntacticSugar\SwitchDemo.java
参数是cp,路径是.java文件的路径

javap -c D:\JVM_Study\out\production\JVM_Study\SyntacticSugar\SwitchDemo.class
参数是c
路径是的.class文件路径
3.1Java编译与反编译

~~~java
java cp D:\JVM_Study\src\SyntacticSugar\SwitchDemo.java
参数是cp,路径是.java文件的路径

javap -c D:\JVM_Study\out\production\JVM_Study\SyntacticSugar\SwitchDemo.class
参数是c
路径是的.class文件路径

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • java语法糖之jdk迭代的新特性汇总

    语法糖(Syntactic sugar) 是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用.通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会. 糖1:for-each 功能和传统的fori相似 代码样例 public class Test { public static void main(String[] args) { int[] num = new in

  • Java语法糖之个数可变的形参的实现

    1. 背景 从JDK1.5开始,Java支持个数可变的形参,类似: public class ParamDemo { public static void main(String[] args) { String basketball = "篮球"; String football = "足球"; showSports(basketball, football); } /** * 使用个数可变形参的方法 */ public static void showSport

  • Java8语法糖之Lambda表达式的深入讲解

    一.Lambda表达式简介 Lambda表达式,是Java8的一个新特性,也是Java8中最值得学习的新特性之一.(另一个新特性是流式编程.) Lambda表达式,从本质上讲是一个匿名方法.可以使用这个匿名方法,实现接口中的方法. 功能:通常使用Lambda表达式,是为了简化接口实现的.关于接口实现可以有多种方式实现,例如:①设计接口的实现类.②使用匿名内部类.但是③使用lambda表达式,比这两种方式都简单. 要求:lambda表达式,只能实现函数式接口:即一个接口中,要求实现类必须实现的抽象

  • Java 中的语法糖,真甜

    我把自己以往的文章汇总成为了 Github ,欢迎各位大佬 star https://github.com/crisxuan/bestJavaer 我们在日常开发中经常会使用到诸如泛型.自动拆箱和装箱.内部类.增强 for 循环.try-with-resources 语法.lambda 表达式等,我们只觉得用的很爽,因为这些特性能够帮助我们减轻开发工作量:但我们未曾认真研究过这些特性的本质是什么,那么这篇文章,cxuan 就来为你揭开这些特性背后的真相. 语法糖 在聊之前我们需要先了解一下 语法

  • 不了解这12个语法糖,别说你会Java

    本文从 Java 编译原理角度,深入字节码及 class 文件,抽丝剥茧,了解 Java 中的语法糖原理及用法,帮助大家在学会如何使用 Java 语法糖的同时,了解这些语法糖背后的原理. 语法糖 语法糖(Syntactic Sugar),也称糖衣语法,是由英国计算机学家 Peter.J.Landin 发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用.简而言之,语法糖让程序更加简洁,有更高的可读性. 有意思的是,在编程领域,除了语法糖,还有语法盐

  • JAVA语法糖原理你知道吗

    目录 Java语法糖 1.基本概念 1.1语法糖 1.2解语法糖 2.常见糖块 2.1 switch 支持 String 与枚举 2.2泛型 2.3自动装箱与拆箱 2.4方法变长参数 2.5枚举 2.6条件编译 2.7 for : each循环 3.最后 3.1Java编译与反编译 总结 Java语法糖 ​ 几乎所有的编程语言都或多或少提供过一些语法糖来方便程序员的代码开发,这些语法糖虽然不会提供实质性的功能改进,但是它们或能提高效率,或能提升语法的严谨性,或能减少编码出错的机会. 1.基本概念

  • 深入理解Java基础之try-with-resource语法糖

    背景 众所周知,所有被打开的系统资源,比如流.文件或者Socket连接等,都需要被开发者手动关闭,否则随着程序的不断运行,资源泄露将会累积成重大的生产事故. 在Java的江湖中,存在着一种名为finally的功夫,它可以保证当你习武走火入魔之时,还可以做一些自救的操作.在远古时代,处理资源关闭的代码通常写在finally块中.然而,如果你同时打开了多个资源,那么将会出现噩梦般的场景: public class Demo { public static void main(String[] arg

  • Java switch关键字原理及用法详解

    这篇文章主要介绍了Java中 switch关键原理及用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Switch语法 switch作为Java内置关键字,却在项目中真正使用的比较少.关于switch,还是有那么一些奥秘的. 要什么switch,我有if-else 确实,项目中使用switch比较少的一个主要原因就在于它的作用能被if-else代替,况且switch对类型的限制,也阻碍了switch的进一步使用. 先看看switch的语法

  • java的继承原理与实现方法详解

    本文实例讲述了java的继承原理与实现方法.分享给大家供大家参考,具体如下: 继承 1.java中是单继承的.每个子类只有一个父类. 语法:子类 extends 父类 2.在java中,即使没有声明父类,也有一个隐含的父类,就是Object类 3.在子类中可以使用super来调用父类的方法 4.继承中的构造方法问题 在new一个子类实例的过程中,会优先自动调用父类默认的无参数构造方法,然后再调用子类的构造方法.如果父类没有默认的构造方法,只有带参数的构造方法,此时就会出错. 除了由jvm自动调用

  • JS为什么说async/await是generator的语法糖详解

    关于async的介绍,在阮一峰的ES6入门教程中说到: async 函数是什么?一句话,它就是 Generator 函数的语法糖. 可是,为什么这么说呢? 首先,比如说有一个异步操作,使用 async/await 语法来以同步模拟异步操作. 使用 async/await 实现一个 sleep 的功能 function sleep(time) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(1); },

  • Java 的抽象类原理与用法分析

    本文实例讲述了Java 的抽象类原理与用法.分享给大家供大家参考,具体如下: Java 的抽象类 用abstract关键字来修饰一个类时,这个类叫做抽象类: 用abstract来修饰一个方法时,该方法叫做抽象方法. 抽象方法:只有方法的声明,没有方法的实现.以分号结束:abstract int abstractMethod(int a ); 含有抽象方法的类必须被声明为抽象类. 抽象类不能被实例化.抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体.若没有重写全部的抽象方法,

随机推荐