Java中的6颗语法糖

转载自 Java中的6颗语法糖

语法糖(Syntactic Sugar),也称糖衣语法,指在计算机语言中添加的某种语法,这种语法对语言本身功能来说没有什么影响,只是为了方便程序员的开发,提高开发效率。说白了,语法糖就是对现有语法的一个封装。

Java作为一种与平台无关的高级语言,当然也含有语法糖,这些语法糖并不被虚拟机所支持,在编译成字节码阶段就自动转换成简单常用语法。

一般来说Java中的语法糖主要有以下几种:

  1. 泛型与类型擦除

  2. 自动装箱与拆箱

  3. 变长参数

  4. 增强for循环

  5. 内部类

  6. 枚举类

泛型与类型擦除

Java语言并不是一开始就支持泛型的。在早期的JDK中,只能通过Object类是所有类型的父类和强制类型转换来实现泛型的功能。强制类型转换的缺点就是把编译期间的问题延迟到运行时,JVM并不能为我们提供编译期间的检查。

在JDK1.5中,Java语言引入了泛型机制。但是这种泛型机制是通过类型擦除来实现的,即Java中的泛型只在程序源代码中有效(源代码阶段提供类型检查),在编译后的字节码中自动用强制类型转换进行替代。也就是说,Java语言中的泛型机制其实就是一颗语法糖,相较与C++、C#相比,其泛型实现实在是不那么优雅。

/**
* 在源代码中存在泛型
*/
public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();map.put("hello","你好");String hello = map.get("hello");System.out.println(hello);}/**
* 在源代码中存在泛型
*/
public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();map.put("hello","你好");String hello = map.get("hello");System.out.println(hello);}

当上述源代码被编译为class文件后,泛型被擦除且引入强制类型转换

public static void main(String[] args) {HashMap map = new HashMap(); //类型擦除map.put("hello", "你好");String hello = (String)map.get("hello");//强制转换System.out.println(hello);}

自动装箱与拆箱

Java中的自动装箱与拆箱指的是基本数据类型与他们的包装类型之间的相互转换。

我们知道Java是一门面向对象的语言,在Java世界中有一句话是这么说的:“万物皆对象”。但是Java中的基本数据类型却不是对象,他们不需要进行new操作,也不能调用任何方法,这在使用的时候有诸多不便。因此Java为这些基本类型提供了包装类,并且为了使用方便,提供了自动装箱与拆箱功能。自动装箱与拆箱在使用的过程中,其实是一个语法糖,内部还是调用了相应的函数进行转换。

下面代码演示了自动装箱和拆箱功能

public static void main(String[] args) {Integer a = 1;int b = 2;int c = a + b;System.out.println(c);}

经过编译后,代码如下

public static void main(String[] args) {Integer a = Integer.valueOf(1); // 自动装箱byte b = 2;int c = a.intValue() + b;//自动拆箱System.out.println(c);}

变长参数

所谓变长参数,就是方法可以接受长度不定确定的参数。变长参数特性是在JDK1.5中引入的,使用变长参数有两个条件,一是变长的那一部分参数具有相同的类型,二是变长参数必须位于方法参数列表的最后面。变长参数同样是Java中的语法糖,其内部实现是Java数组。

public class Varargs {public static void print(String... args) {for(String str : args){System.out.println(str);}}public static void main(String[] args) {print("hello", "world");}}

编译为class文件后如下,从中可以很明显的看出变长参数内部是通过数组实现的

public class Varargs {public Varargs() {}public static void print(String... args) {String[] var1 = args;int var2 = args.length;//增强for循环的数组实现方式for(int var3 = 0; var3 < var2; ++var3) {String str = var1[var3];System.out.println(str);}}public static void main(String[] args) {//变长参数转换为数组print(new String[]{"hello", "world"});}}

增强for循环

增强for循环与普通for循环相比,功能更强并且代码更简洁。增强for循环的对象要么是一个数组,要么实现了Iterable接口。这个语法糖主要用来对数组或者集合进行遍历,其在循环过程中不能改变集合的大小。

public static void main(String[] args) {String[] params = new String[]{"hello","world"};//增强for循环对象为数组for(String str : params){System.out.println(str);}List<String> lists = Arrays.asList("hello","world");//增强for循环对象实现Iterable接口for(String str : lists){System.out.println(str);}
}

编译后的class文件为

public static void main(String[] args) {String[] params = new String[]{"hello", "world"};String[] lists = params;int var3 = params.length;//数组形式的增强for退化为普通forfor(int str = 0; str < var3; ++str) {String str1 = lists[str];System.out.println(str1);}List var6 = Arrays.asList(new String[]{"hello", "world"});Iterator var7 = var6.iterator();//实现Iterable接口的增强for使用iterator接口进行遍历while(var7.hasNext()) {String var8 = (String)var7.next();System.out.println(var8);}}

内部类

内部类就是定义在一个类内部的类Java语言中之所以引入内部类,是因为有些时候一个类只在另一个类中有用,我们不想让其在另外一个地方被使用。内部类之所以是语法糖,是因为其只是一个编译时的概念,一旦编译完成,编译器就会为内部类生成一个单独的class文件,名为outer$innter.class。

public class Outer {class Inner{}
}

使用javac编译后,生成两个class文件Outer.class和Outer$Inner.class,其中Outer$Inner.class的内容如下:

class Outer$Inner {Outer$Inner(Outer var1) {this.this$0 = var1;}
}

内部类分为四种:成员内部类、局部内部类、匿名内部类、静态内部类,每一种都有其用法,这里就不介绍了

枚举类型

枚举类型就是一些具有相同特性的类常量java中类的定义使用class,枚举类的定义使用enum。在Java的字节码结构中,其实并没有枚举类型,枚举类型只是一个语法糖,在编译完成后被编译成一个普通的类。这个类继承java.lang.Enum,并被final关键字修饰。

public enum Fruit {APPLE,ORINGE
}

使用jad对编译后的class文件进行反编译后得到:

//继承java.lang.Enum并声明为final
public final class Fruit extends Enum
{public static Fruit[] values(){return (Fruit[])$VALUES.clone();}public static Fruit valueOf(String s){return (Fruit)Enum.valueOf(Fruit, s);}private Fruit(String s, int i){super(s, i);}//枚举类型常量public static final Fruit APPLE;public static final Fruit ORANGE;private static final Fruit $VALUES[];//使用数组进行维护static{APPLE = new Fruit("APPLE", 0);ORANGE = new Fruit("ORANGE", 1);$VALUES = (new Fruit[] {APPLE, ORANGE});}}

Java远不止这些语法糖,JDK7、JDK8添加的新特性都有很多高级的语法糖。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330827.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

其他流总述

1.转换流 InputStreamReader: 把InputStream转换为Reader&#xff0c;可以指定编码表 OutputStreamWriter: 把OutputStream转换为Writer&#xff0c;可以指定编码表 //转换流[用于指定编码表读入或写出] public class Demo1 {public static void main(String[] args) throws …

如何查阅相关工作所用到的文献资料

以百度学术为例。 step1&#xff1a;百度学术里输入 最关键的paper 名称&#xff0c;并点击 被引量链接&#xff1b; step2&#xff1a;通过最近年份 或 其他条件 筛选paper &#xff08;注意看发表期刊或会议的级别&#xff09; step3&#xff1a;主要看paper的摘要或 intro&…

递归算法介绍及Java应用实战

转载自 递归算法介绍及Java应用实战 什么是递归算法 递归算法是把问题转化为规模缩小了的同类问题的子问题&#xff0c;然后递归调用函数&#xff08;或过程&#xff09;来表示问题的解。一个过程(或函数)直接或间接调用自己本身&#xff0c;这种过程(或函数)叫递归过程(或函数…

K最近邻分类器

转自&#xff1a; http://www.cnblogs.com/qwertWZ/p/4582096.html 本章介绍了《机器学习实战》这本书中的第一个机器学习算法&#xff1a;k-近邻算法&#xff0c;它非常有效而且易于掌握。首先&#xff0c;我们将探讨k-近邻算法的基本理论&#xff0c;以及如何使用距离测量的方…

多线程安全问题1

1.问题的产生 原因&#xff1a;多个线程操作同一个共享数据。 原理&#xff1a;多个线程在访问共享数据时&#xff0c;由于CPU的随机性&#xff0c;一个线程还没有执行完&#xff0c;执行权被其他线程抢走了&#xff0c;这个时候就有可能出现线程安全问题。 解决方式&#xff…

Java父类强制转换子类原则

转载自 Java父类强制转换子类原则最近&#xff0c;微信群友在讨论子类父类的转换问题&#xff0c;其实不难&#xff0c;给大家用实例来说明一下就很明了了。 我们知道Java中子类转换成父类是没有任何问题的&#xff0c;那父类可以转换成子类吗&#xff1f; 来看下面这段程序&am…

生产者和消费者案例

1.案例描述 这里以吃饭为例&#xff0c;假设有一个桌子&#xff0c;用来存汉堡包&#xff0c;然后有厨师和消费者&#xff0c;厨师往桌子上放汉堡包&#xff0c;消费者从桌子上取走汉堡包。当两者在一个时间段同时进行多次自己的操作时&#xff0c;很明显这就是多线程编程的生…

用Python开始机器学习(4:KNN分类算法)

转自&#xff1a; http://blog.csdn.net/lsldd/article/details/41357931 1、KNN分类算法 KNN分类算法&#xff08;K-Nearest-Neighbors Classification&#xff09;&#xff0c;又叫K近邻算法&#xff0c;是一个概念极其简单&#xff0c;而分类效果又很优秀的分类算法。 他的…

Mybatis传递多个参数的4种方式

转载自 Mybatis传递多个参数的4种方式&#xff08;干货&#xff09;现在大多项目都是使用Mybatis了&#xff0c;但也有些公司使用Hibernate。使用Mybatis最大的特性就是sql需要自己写&#xff0c;而写sql就需要传递多个参数。面对各种复杂的业务场景&#xff0c;传递参数也是一…

多线程安全问题2

1.volatile关键字 <1>作用&#xff1a;强制线程每次在使用的时候,都会看一下共享区域最新的值[用于提供线程安全] <2>与synchronized的区别和联系&#xff1a; 把代码块声明为 synchronized&#xff0c;有两个重要后果&#xff0c;通常是指该代码具有 原子性&…

Maven Optional Exclusions使用区别

转载自 Maven Optional & Exclusions使用区别 Optional和Exclusions都是用来排除jar包依赖使用的&#xff0c;两者在使用上却是相反。 Optional定义后&#xff0c;该依赖只能在本项目中传递&#xff0c;不会传递到引用该项目的父项目中&#xff0c;父项目需要主动引用该依赖…

为什么jdk的CLASSPATH环境变量需要设置rt.jar 和 tools.jar

How Classes are Found 中有说明&#xff1a;&#xff08;java启动类文件在 rt.jar中&#xff0c; 而 工具类文件在 tools.jar 中&#xff09; How the Java Launcher Finds Classes The Java launcher, java, initiates the Java virtual machine. The virtual machine searc…

线程池的实现

1.创建线程池 API提供了一个工具类叫Executors&#xff0c;可以用它的方法生成不同特点的线程池&#xff0c;返回一个ExecutorService对象。 <1>Executors.newCachedThreadPool() 【池子中默认是空的&#xff0c;最多可以容纳int类型的最大值】 <3>Executors.new…

JSON Web Token (JWT),服务端信息传输安全解决方案

转载自 JSON Web Token (JWT)&#xff0c;服务端信息传输安全解决方案JWT介绍 JSON Web Token(JWT)是一种开放标准(RFC 7519)&#xff0c;它定义了一种紧凑独立的基于JSON对象在各方之间安全地传输信息的方式。这些信息可以被验证和信任&#xff0c;因为它是数字签名的。JWTs可…

thinking-in-java(18) java io

【0】README&#xff1a;本篇文章是以 thinking in java 为基础梳理的&#xff1b; 【18.1.1 目录列表器】 // 传入正则表达式以过滤文件名如 (.*src)* public class DirList {public static void main(String[] args) {File path new File(".");String[] list; i…

并发工具类【线程安全相关的类】

1.Hashtable和ConcurrentHashMap Hashtable&#xff1a;哈希表结构&#xff08;数组链表&#xff09;&#xff0c;线程安全的(同步代码块&#xff0c;效率低) ConcurrentHashMap&#xff1a; jdk7:采用Segment数组[不会扩容] HashEntry[二次哈希计算存入的位置,可扩容]&#…

JSON Web Token (JWT)生成Token及解密实战

转载自 JSON Web Token (JWT)生成Token及解密实战昨天讲解了JWT的介绍、应用场景、优点及注意事项等&#xff0c;今天来个JWT具体的使用实践吧。从JWT官网支持的类库来看&#xff0c;jjwt是Java支持的算法中最全的&#xff0c;推荐使用&#xff0c;网址如下。https://github.co…

java中两个map的融合(两个map有相同字段)

试想这样一个场景&#xff1a; 数据库表中 有 城市信息表 city_tbl&#xff1b; 有院士信息表 ys_tbl &#xff0c;其中院士有城市id字段&#xff08;id&#xff09;&#xff1b; 但是不是所有城市都有院士&#xff1b; 我们想要得到 城市的详细信息&#xff0c;包括院士个数…

网络编程实现

1.网络编程三要素 1.IP地址&#xff1a;网络中设备的唯一标识IPv4: 由4个字节组成&#xff0c;点分十进制表示法IPv6: 由16个字节组成&#xff0c;冒分十六进制表示法"127.0.0.1"本地主机网络地址【用于测试】相关命令&#xff1a;ipconfig: 查看本机在当前网络环境…

通用唯一标识码UUID的介绍及使用

转载自 通用唯一标识码UUID的介绍及使用。什么是UUID&#xff1f; UUID全称&#xff1a;Universally Unique Identifier&#xff0c;即通用唯一识别码。 UUID是由一组32位数的16进制数字所构成&#xff0c;是故UUID理论上的总数为16^32 2^128&#xff0c;约等于3.4 x 10^38。也…