通常,编译器会生成代码以执行装箱和拆箱。但是,如果不需要带框的值,编译器怎么办?(Oracle标准)编译器是否足够智能以优化它?
看一下这个方法:
public static void requireInRange(int index, Object[] array) { if(index < 0 || index >= array.length) throw new IndexOutOfBoundsException(); }
唯一相关的信息是array.length,因此将例如数组的每个值装箱将是无用的。像下面的代码:
array.length
int[] anArray = {3, 4, 2}; requireInRange(3, anArray);
编译器会实际插入用于对数组的每个值进行装箱的代码吗?
您的代码中没有自动装箱。实际上,鉴于:
public static void requireInRange(int index, Object[] array) { ... } int[] anArray = {3, 4, 2}; requireInRange(3, anArray); // DOES NOT COMPILE!!!
虽然int可以将an自动装箱到Integer,int[]但Java 不会 将an自动装箱到Integer[]。您可以编写库函数来执行此操作,但是该语言将不会促进这种转换。
int
Integer
int[]
Integer[]
实际上,这是许多关于例如Arrays.asList(anIntArray)“损坏”的困惑的根源,因为返回的List<Integer>实际上不是一个元素,而是返回了a ,而不是返回a List<int[]>。
Arrays.asList(anIntArray)
List<Integer>
List<int[]>
Java语言指南/自动装箱中的报价:
将自动装箱和拆箱用于科学计算或其他对性能敏感的数字代码是不合适的。An Integer不能替代an int; 自动装箱和拆箱模糊了原始类型和引用类型之间的区别,但是并不能消除它们。
简而言之,每当自动装箱发生时,性能肯定会受到影响。某些事情可以缓解这种情况,例如,这些类型中内置的缓存机制。这就是为什么您得到以下信息的原因:
System.out.println( ((Integer) 0) == ((Integer) 0) ); // true System.out.println( ((Integer) 10000) == ((Integer) 10000) ); // false (implementation-specific)
这里发生的是,当0被 自动 装箱,没有 新的 Integer实际创建的实例:在一定范围内的值被 缓存 为自动装箱宗旨,以有助于提高性能。10000在大多数实现中,它可能不在此范围内,但是某些JVM实现确实允许您在必要时指定缓存范围。
0
10000
有很多方法可以帮助您requireInRange使用任何类型的数组。不幸的是,使用Java的原语数组常常意味着很多重复。这意味着提供过载int[],boolean[],byte[],Object[],分别等。
requireInRange
boolean[]
byte[]
Object[]
一个更简洁的选择是使用反射,但这有其优点和缺点。一般来说,对于大多数情况而言,反射不是首选的解决方案。
话虽如此,java.lang.reflect.Array确实有一个可以返回_ANY_ 数组长度的方法。它不是类型安全的(就像大多数反射机制一样);传递非数组编译,但在运行时抛出。int getLength(Objectarray) static __IllegalArgumentException
java.lang.reflect.Array
int getLength(Objectarray)
static
IllegalArgumentException
-(受到的启发java.util.Arrays)
java.util.Arrays