在我们讲述 时,其中涉及到了一个解语法糖。
语法糖只不过是一种程序的表达式,语法糖可以提高程序的可读性,语法糖经过编译后,将会恢复原来的样貌。
- 泛型和类型擦除
- foreach语法
1. 泛型和类型擦除
泛型的本质是参数化类型,这个参数类型可被用在接口、类、方法上,分别称为泛型接口、泛型类、泛型方法。
1.1 为什么要引入泛型
没有泛型的Java只能通过Object强制转换成具体的类型,这种写法极其不美观,而且需要程序员去保证这个强转操作的正确性,否则极有可能在虚拟机运行的时候抛出ClassCastException。
1.2 类型擦除
Java中的泛型是伪泛型,泛型只会在程序 源码 中存在,在编译后的 class文件 中,参数类型将会被抹除(类型擦除)。
public class ClassTest {
public static void main(String[] args) {
List<String> result = new ArrayList<>();
result.add("test");
System.out.println(result.get(0));
}
}
上述Java代码经编译过后,会生成class文件,我们再对class文件 反编译 ,得到的程序代码如下:
public class ClassTest {
public ClassTest() {
}
public static void main(String[] var0) {
ArrayList var1 = new ArrayList();
var1.add("test");
System.out.println((String)var1.get(0));
}
}
这里我们可以看到,泛型中的String已经被完全擦除,并且当我们从list中取回数据时自动强转成了String。Java编译器会自动将泛型擦除,将强转添加。
public class ClassTest {
public static void test(List<String> args) {
}
public static void test(List<Integer> args) {
}
}
上述代码编译不会通过,因为List和List最终都会变为List。
1.3 Signature
Signature是属性表中的一项属性,可作用于类、方法表、以及字段表。
由于Java泛型的引入,各种场景下的方法调用都可能产生影响,如在泛型类中如何获取参数化类型。
public class ClassTest {
public List<Double> test(List<String> args, List<Integer> args1) {
return null;
}
}
上述源码编译成class文件以后,我们在使用java -p指令来看一下字节码文件,如下图:
Signature一个重要的作用就是保存了参数化类型,这样以后通过这个属性我们就可以获取到参数化类型。
2. foreach语法
public class ClassTest {
public static void main(String[] args) {
List<String> result = new ArrayList<>();
result.add("test");
for (String r : result) {
System.out.println(r);
}
}
}
上述foreach语法在经过编译后,变成了使用Iterator进行遍历。
public class ClassTest {
public ClassTest() {
}
public static void main(String[] var0) {
ArrayList var1 = new ArrayList();
var1.add("test");
Iterator var2 = var1.iterator();
while(var2.hasNext()) {
String var3 = (String)var2.next();
System.out.println(var3);
}
}
}
通过上述我们也可以看出,如果想要使用foreach语法,该类必须要实现Iterable接口。
Java中除了上述两种语法糖,还有诸如内部类、自动装箱、自动拆箱、try语句定义和关闭资源等,分析方法均如上述,感兴趣的读者可以自行分析。
本期的Java语法糖介绍到这,我是shysh95,我们下期再见!!!