一、简介
【概念】
语法糖(Syntactic sugar),指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。
【特点】
只存在于编译期, 在编译器将.java源文件编译成.class字节码时, 会进行解语法糖操作, 还原最原始的基础语法结构;
不会提供实质性的功能改进,但是能提高我们开发的效率。
二、常见语法糖
1、自动装箱与拆箱
【概念】
自动装箱:将基本数据类型自动转换成对应的包装类(一般用于基本类型数据处于需要对象的环境中);
自动拆箱:将包装类自动转换成对应的基本数据类型(当需要值时)。
【出现原因】
Java早年设计缺陷。基础类型是数据,不是对象,也不是Object的子类。把一个基本类型包装成一个类,可以使这个类型具有很多可以调用的方法。
Java向面像对象语言的靠近。其实Java还不算是很纯的面向对象的语言。真正的面向对象,是没有基本数据类型的。它只有一种类型,就是对象。
在泛型中,基本类型是不可以做泛型参数的。
【原理】
自动装箱都是通过包装类的valueOf()方法来实现的;
自动拆箱都是通过包装类对象的xxxValue()来实现的。
【示例】
Integer i = 10; //装箱,等价于Integer i = Integer.valueOf(10); int n = i; //拆箱,等价于int n = i.intValue();
【使用场景】
当我们把基本数据类型放入集合类中的时候,会进行自动装箱;
包装类与基本数据类型进行比较运算,是先将包装类进行拆箱成基本数据类型,然后进行比较的;
两个包装类型之间的运算,会被自动拆箱成基本类型进行。
【注意事项】
所有整型包装类对象之间值的比较,全部使用equals方法比较,原因如下,详请见包装类的缓存机制;
public static void main(String[] args) { Integer i1 = 1222; Integer i2 = 1222; Integer i3 = 12; Integer i4 = 12; System.out.println("i1 是否等于 i2:" + (i1==i2)) ; System.out.println("i3 是否等于 i4:" + (i3==i4)) ; }
i1 是否等于 i2:false i3 是否等于 i4:true
一个for循环中有大量拆装箱操作,会浪费很多资源。
2、可变参数
【概述】
在具体实际开发过程中,有时方法中参数的个数是不确定的。
【语法】
methodName({paramList},paramType...paramName)
methodName:方法名称;
paramList:方法的固定参数列表;
paramType:可变参数的类型;
...:声明可变参数的标识;
paramName:可变参数名称。
【注意】可变参数必须定义在参数列表的最后。
【例子】
public class StudentTestMethod { // 定义输出考试学生的人数及姓名的方法 public void print(String...names) { int count = names.length; // 获取总个数 System.out.println("本次参加考试的有"+count+"人,名单如下:"); for(int i = 0;i < names.length;i++) { System.out.println(names[i]); } } public static void main(String[] args) { // TODO Auto-generated method stub StudentTestMethod student = new StudentTestMethod(); student.print("张强","李成","王勇"); // 传入3个值 student.print("马丽","陈玲"); } }
3、泛型
3.1 简介
【概述】
泛型的本质是参数化类型,它提供了编译时类型安全监测机制,通过这个机制,我们可以在编译时检查类型安全,泛型所有的强制转换都是自动、隐式的,只要编译时没有问题,运行时就不会出现ClassCastException(类型转换异常),极大地提高代码的可读性、复用性及安全性。
【作用】
将类型明确的事情延后到创建对象或调用方法时,再去明确的特殊的类型;
调用方法时,不用强转对象、写很多重复方法;
提高代码复用性和可读性(一套代码可支持不同的类型,不用强转,更加简洁);
提高程序安全性。
【使用场景】
使用在不想写多个重载函数的场景;
使用在用户希望返回他自定义类型的返回值场景。例如:Json 返回 Java bean ;
在使用反射的应用中,也经常使用泛型。例如:Class<T> ;
使用在约束对象类型的场景,用来定义边界(T extends ...)。例如:JDK 集合 List,Set ;
使用在网页、资源分析或返回的场景。
3.2 泛型擦除
【概念】
在JVM中没有泛型这一概念, 只有普通方法和普通类, 所有泛型类的泛型参数都会在编译时期被擦除, 所以泛型类并没有自己独有的Class类对象。
【示例】
public class GenericType { public static void main(String[] args) { ArrayList<String> arrayString=new ArrayList<String>(); ArrayList<Integer> arrayInteger=new ArrayList<Integer>(); // List<Integer> 和 List<String> 类型在编译后,都会变成 List 类型(原始类型) System.out.println(arrayString.getClass()==arrayInteger.getClass()); //true } }