JVM(四)——编译期的处理

编译期处理(语法糖)

所谓的语法糖 ,其实就是指 java 编译器把 *.java 源码编译为 *.class 字节码的过程中,自动生成
和转换的一些代码,主要是为了减轻程序员的负担。大多数是在 jdk5 及 jdk7 做的处理。

1)默认构造器

创建一个类后,如果没有构造器,编译器会自动为我们添加无参的构造器,且调用父类的无参构造方法。

2)自动拆装箱

由编译器在编译阶段完成基本类型和包装类型之间的转换

3)泛型集合取值

泛型也是在 JDK 5 开始加入的特性,但 java 在编译泛型代码后会执行 泛型擦除 的动作,即泛型信息
在编译为字节码之后就丢失了,实际的类型都当做了 Object 类型来处理:

public class Candy3 {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		list.add(10); // 实际调用的是 List.add(Object e)
		Integer x = list.get(0); // 实际调用的是 Object obj = List.get(int index);
	}
}

擦除的是字节码上的泛型信息,可以看到 LocalVariableTypeTable 仍然保留了方法参数泛型的信息

public cn.itcast.jvm.t3.candy.Candy3();
	descriptor: ()V
	flags: ACC_PUBLIC
	Code:
		stack=1, locals=1, args_size=1
			0: aload_0
			1: invokespecial #1 // Method java/lang/Object."<init>":()V
			4: return
		LineNumberTable:
			line 6: 0
		LocalVariableTable:
			Start Length Slot Name Signature
			  0     5     0   this Lcn/itcast/jvm/t3/candy/Candy3;
	public static void main(java.lang.String[]);
		descriptor: ([Ljava/lang/String;)V
		flags: ACC_PUBLIC, ACC_STATIC
		Code:
			stack=2, locals=3, args_size=1
				0: new #2 // class java/util/ArrayList
				3: dup
				4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
				7: astore_1
				8: aload_1
				9: bipush 10
				11: invokestatic #4 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
				// 14 行 执行完后 擦除了泛型信息 当作了 Object 类型来处理 list.add(Object)
				14: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z						
				19: pop
				20: aload_1
				21: iconst_0
				// 22 泛型擦除 Object obj = get(int index)
				22: invokeinterface #6, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
				// 27 强制类型转换 将 Object 转为 Integer
				27: checkcast #7 // class java/lang/Integer
				30: astore_2
				31: return
			LineNumberTable:
				line 8: 0
				line 9: 8
				line 10: 20
				line 11: 31
			LocalVariableTable:
				Start Length Slot Name Signature
				  0     32    0   args [Ljava/lang/String;
				  8     24    1   list Ljava/util/List;
			LocalVariableTypeTable:
				Start Length Slot Name Signature
				  8     24     1  list Ljava/util/List<Ljava/lang/Integer;>;

4)可变参数

可变参数 String... args其实是一个 String[] args

5)foreach 循环

仍是 JDK 5 开始引入的语法糖,数组的循环:
普通 foreach 循环,底层实际上是 普通 for 循环。
对于集合(实现了 Iterable 接口)的 foreach 循环,底层使用的是 迭代器。

6)switch 字符串

switch 可以作用于字符串和枚举类。编译器先根据字符串的hashCode值作为 case 条件,避免哈希从图然后又根据 equals 方法判断字符串是否符合条件。再定义一个 switch 结构专门用来处理业务逻辑。
switch 配合 String 和枚举使用时,变量不能为null

7)switch 枚举

8)枚举类

枚举类中的成员,实际上是 枚举类中的实例对象且个数是一定的。
枚举实际上是单例设计模式的一种体现。

9)try-with-resources(资源的自关闭)

资源对象实现 AutoCloseable 接口后,不需要在 finally 块中手动关闭资源,例如一些流、连接和容器的关闭。编译器会帮助生成关闭资源代码。而且内层和外层(finally 块)的异常信息都不会丢失。

10)方法重写时的桥接方法

方法重写时返回值类型分两种:

  • 父类和子类的返回值类型一样 (父 Integer, 子Integer)
  • 子类的返回值类型是父类返回值类型的子类 (父 Number, 子 Integer)

例如在反编译后的代码中。

class B extends A {
	// 父类的方法
	public Integer m() {
		return 2;
	}
	// 此方法才是真正重写了父类 public Number m() 方法
	public synthetic bridge Number m() {
		// 调用 public Integer m()
		return m();
	}
}

11)匿名内部类

匿名内部类会额外生成一个类(final修饰)。如果匿名内部类中引用了外部的变量,那么在通过匿名内部类创建额外的类时,会把引用的变量当作本类的成员变量,且在原类中(使用了匿名内部类),向匿名内部类中传递的变量必须是 final 的。
引用局部变量的匿名内部类,源代码:

public class Candy11 {
	public static void test(final int x) {
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				System.out.println("ok:" + x);
			}
		};
	}
}

转换后代码:

// 额外生成的类
final class Candy11$1 implements Runnable {
	int val$x;
	Candy11$1(int x) {
		this.val$x = x;
	}
	public void run() {
		System.out.println("ok:" + this.val$x);
	}
}
public class Candy11 {
	public static void test(final int x) {
		Runnable runnable = new Candy11$1(x);
	}
}

在创建Candy11$1 对象时,将 x 的值赋值给了 Candy11$1 对象的 val$x 属性,所以 x 不应该再发生变
化了,如果变化,那么 val$x 属性没有机会再跟着一起变化

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值