语法糖 ? ? 其实就是指 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);
? ?}
}
?
?
|