编译期语法糖(三)
try-with-resources
1 | public class Demo06_1 { |
使用try-catch-resources 可以不用写finally语句块,编译期会帮助生成关闭资源代码.
代码会被转换为:
1 | public class Demo06_1 { |
可以看出,jvm帮我们生成了finally代码,并且未防止close和我们的代码同时出现异常,异常丢失的情况,还做了优化.
我们可以测试一下我们的代码,和资源close同时抛出异常的情况.
代码如下:
1 | public class Demo06_2 { |
运行结果如下:
1 | java.lang.ArithmeticException: / by zero |
所以可以看出,我们自己代码的异常/ by zero ,以及资源Close时异常资源Close时异常! 都有保留,并且正常抛出.
方法重写时的桥接方法
我们都知道,方法重写时的返回值分两种情况.
- 父子类的返回值完全一致
- 子类的返回值可以是父类返回值的子类
1 | public class Demo06_3 { |
对于子类,java编译器会做如下处理:
1 | class B extends Demo06_3{ |
我们可以使用反射来验证一下
1 | public static void main(String[] args) { |
打印结果:
1 | public java.lang.Integer demo06.B.n() |
可以看出,确实有两个方法.一个方法是我们自己写的,另一个方法是合成后的桥接方法.
匿名内部类
1 | public class Demo06_4 { |
转换后代码:
1 | //额外生成的类 |
1 | public class Demo06_4 { |
原来的main方法,就新建了一个额外生成的类来调用.
我们再来看下使用外部参数的匿名内部类
1 | public class Demo06_5 { |
转换后代码:
1 | //额外生成的类 |
1 | public static void test(final int i){ |
为了使匿名内部流可以使用外部的变量,在编译期,会生成对应的参数
然后通过构造方法传给额外生成的类.
这也是为什么匿名内部类只能使用final参数的原因.