自动装箱和拆箱,可变长参数,数值字面量

自动装箱和拆箱,可变长参数,数值字面量

第一节 自动装箱和拆箱

简介

  我们知道Java类型要么是引用类型,要么是原始类型。但泛型只能绑定到引用类型,这是由泛型内部的实现方式造成的。因此Java提供了一个自动装箱/拆箱机制,来帮助开发者自动转换两种类型。

  • 装箱:将基本类型用它们对应的引用类型包装起来。
  • 拆箱:将包装类型转换为基本数据类型。

  Java使用自动装箱和拆箱机制,节省了常用数值的内存开销和创建对象的开销,提高了效率,由编译器来完成,编译器会在编译期根据语法决定是否进行装箱和拆箱动作。装箱后的值本质上就是把原始类型包裹起来,自然要占用更多的空间和获取时额外的内存搜索。Java 8为函数式接口提供了一个避免自动装箱的方法,如使用InePredicate相较Predicate就不会进行装箱。

场景

1
2
3
4
5
6
7
8
9
//装箱
Integer i = 1;
//编译器自动处理为->
//Integer i = Integer.valueOf(1);

//拆箱
int i1 = i;
//编译器自动处理为->
//int i1 = i.intValue();

作用

  也可以把包装类型的作用纳入:

  1. 方便开发人员不用处理基本类型和包装类的转换过程
  2. 包装类扩展了基本类型,可以提供丰富的属性和API
  3. 包装类为泛型提供了支持
  4. 包装类把基本类型封装为了抽象对象,也就体现了对象的优点:更好的模拟现实

为什么泛型只能绑定到引用类型

  Java 5首次引入泛型时,需要保持其余现存JVM的后向兼容性,所以对于虚拟机来说ArrayList或ArrayList在运行时是一致的,这种模式叫泛型多态的消除模式。如果Java支持ArrayList<int>这种泛型,那么我们就可以在堆上分配由简单数据值构成的ArrayList对象,但ArrayList容器没办法去了解它所容纳的值到底是什么对象类型,这对于垃圾收集会造成问题,收集器无法判断出比如集合中元素6是一个Integer的引用还是int类型的简单数据。

  C#中,ArrayList或ArrayList在运行时的表示不同,即使它们值相同,但也有足够的运行时类型信息。这些信息可以帮助收集器判断一个字段值是引用还是简单数据。这种模式叫泛型多态的具化模式

  Java未采用具化模式的原因就是需要保持其后向兼容,需要同时兼容JVM和使用了反射且希望进行泛型擦除的遗留代码。


第二节 可变长参数

  可变长参数在Java 1.5时引入,可以使方法将一个任意数目的值作为参数。

1
2
3
4
5
6
7
8
public static void main(String[] args) {
print("1","2","3");
}

public static void print(String... strs){
for(String str : strs)
System.out.println(str);
}

  反编译后如下,String…编译为字符串数组String[],数组长度为参数个数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class VarParm {
public VarParm() {
}

public static void main(String[] var0) {
print("1", "2", "3");
}

public static void print(String... var0) {
String[] var1 = var0;
int var2 = var0.length;

for(int var3 = 0; var3 < var2; ++var3) {
String var4 = var1[var3];
System.out.println(var4);
}

}
}

第三节 数值字面量

  在Java 7引入了数值字面量,允许在整型和浮点型数字中添加下划线“_”,在编译时会被擦除,用来方便阅读

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class NumLiteralValue {
public static void main(String[] args) {
int a = 10_000_000;
System.out.println(a);
}
}

console: 10000000

//Decompile
public class NumLiteralValue {
public NumLiteralValue() {
}

public static void main(String[] var0) {
int var1 = 10000000;
System.out.println(var1);
}
}

参考博客和文章书籍等:

https://zhuanlan.zhihu.com/p/27657548

https://mp.weixin.qq.com/s/6dqFNzfSe88vYMW_r3s3Bw

因博客主未标明不可转载,若内容涉及侵权请及时告知,我会尽快修改和删除相关内容