发布于2021-06-14 10:08 阅读(847) 评论(0) 点赞(19) 收藏(2)
语法糖 ,其实就是指 java 编译器把 *.java 源码编译为 *.class 字节码的过程中,自动生成和转换的一些代码,主要是为了减轻程序员的负担,算是 java 编译器给我们的一个额外福利(给糖吃 )。
编译成class文件后,在没有构造器的前提下,会自动生成无参构造器,该类的无参构造器又会自动生成父类Object的无参构造器super()。
代码片段1会在编译期间被转换为片段2。
泛型也是在 JDK 5 开始加入的特性,但 java 在编译泛型代码后会执行 泛型擦除的动作,即泛型信息在编译为字节码之后就丢失了,实际的类型都当做了 Object 类型来处理。
擦除的是字节码上的泛型信息,可以看到 LocalVariableTypeTable 仍然保留了方法参数泛型的信息。
擦除的是字节码上的泛型信息,可以看到 LocalVariableTypeTable 仍然保留了方法参数泛型的信息。
泛型信息可以在 LocalVariableTypeTable中通过反射的方法获取。
可变参数 String… args 其实是一个 String[] args 。
1、数组的foreach的底层就是for循环
2、集合的foreach第底层就是iterator迭代器。
数组
集合
从 JDK 7 开始,switch 可以作用于字符串和枚举类,这个功能其实也是语法糖
public static void choose(String str) {
byte var2 = -1;
switch(str.hashCode()) {
case 99162322:
if (str.equals("hello")) {
var2 = 0;
}
break;
case 113318802:
if (str.equals("world")) {
var2 = 1;
}
}
switch(var2) {
case 0:
System.out.println("h");
break;
case 1:
System.out.println("w");
}
}
执行了两遍 switch,第一遍是根据字符串的 hashCode 和 equals 将字符串的转换为相应byte 类型,第二遍才是利用byte 执行进行比较。
为什么第一遍时必须既比较 hashCode,又利用 equals 比较呢?
hashCode 是为了提高效率,减少比较的次数;
而 equals 是为了防止 hashCode 冲突,
例如 BM 和 C.,这两个字符串的hashCode值都是 2123 。
从 JDK 7 开始,switch 可以作用于字符串和枚举类,这个功能其实也是语法糖
定义一个合成类数组,数组的长度就是枚举的数据,通过数组的索引来定位枚举的静态的成员常量。
枚举数据(MALE,FEMALE)都是实例对象。
public final class Sex extends Enum{
public static final Sex MALE;
public static final Sex FEMALE;
private static final Sex $VALUES[];
static
{
MALE = new Sex("MALE", 0);
FEMALE = new Sex("FEMALE", 1);
$VALUES = (new Sex[] {
MALE, FEMALE
});
}
private Sex(String s, int i)
{
super(s, i);
}
public static Sex[] values()
{
return (Sex[])$VALUES.clone();
}
public static Sex valueOf(String name)
{
return (Sex)Enum.valueOf(Sex.class, name);
}
}
JDK 7 开始新增了对需要关闭的资源处理的特殊语法 try-with-resources
其中资源对象需要实现 AutoCloseable 接口,例如 InputStream 、 OutputStream 、 Connection 、 Statement 、 ResultSet 等接口都实现了 AutoCloseable ,使用 try-with- resources 可以不用写 finally 语句块,编译器会帮助生成关闭资源代码。
会被转换为:(自动关流)
public class Candy9 {
public Candy9() {
}
public static void main(String[] args) {
try {
InputStream is = new FileInputStream("d:\\1.txt");
Throwable var2 = null;
try {
System.out.println(is);
} catch (Throwable var12) {
var2 = var12; //是代码出现的异常
throw var12;
} finally {
if (is != null) { //判断资源不为空
if (var2 != null) { //如果代码有异常
try {
is.close();
} catch (Throwable var11) { //如果close出现异常,作为被压制异常添加(2个异常都抛出)
var2.addSuppressed(var11);
}
} else {
//如果代码没有异常,close异常就是最后的catch块中的var14
is.close();
}
}
}
} catch (IOException var14) {
var14.printStackTrace();
}
}
}
为什么要设计一个 addSuppressed(Throwable e) (添加被压制异常)的方法呢?
是为了防止异常信息的丢失,将2个异常都抛出。
方法重写时对返回值分两种情况:
1、父子类的返回值完全一致
2、子类返回值可以是父类返回值的子类(JVM在编译的时候会进行优化)
synthetic bridge是JVM内部自动生成的合成方法,对我们是不可见的。这个方法允许方法同名,并且参数一致,并不会违反方法重载的规则。作为一种桥接手段,让子类方法重写真真符合重写的规则。
匿名内部类实际上就是生成一个实现类。
案例:
匿名内部类引用外部变量的时候,这个变量必须为常量(final)。
把外部变量x的值作为参数传给构造方法。
所以外部变量的值不应该发生变化,如果变化,那么实现类中的val$x的值就没办法跟着一起变化,就会导致值不一致。
解决方法:使用数组或者集合存数据。
改变匿名内部类的变量
interface A {
void run();
}
public class Test {
public static void main(String[] args) {
int[] arr = new int[1];
arr[0] = 1;
for (int i = 0; i < 5; i++) {
A a = new A() {
@Override
public void run() {
System.out.println(arr[0]);
}
};
a.run();
arr[0]++;
}
}
}
作者:我爱编程
链接:http://www.javaheidong.com/blog/article/222637/7ec43c55d760a42351c6/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!