08-31-2015
在开发中,我们经常会不在意一些小的性能损失,但是当这些损失积累起来就会引起大问题,我们在开发中还是需要谨小慎微来挖掘任何性能优化方法。
Java提供了基本类型如boolean(8bit)
、int(32bit)
、float(32bit)
、long(64bit)等
。同时也相应提供了自动包装类型java.lang.Boolean
、java.lang.Integer
、java.langFloat
等自动包装类型,通常用于集合类的使用(基本类型无法在集合类中使用)。这是自动包装类型产生的原因。
自动包装类型封装了基本类型常用的方法,我们不用担心功能上的问题。并且基本类型可以直接赋值给自动包装类而不需要转换。
上面的代码看起来基本类型和自动包装类型的使用并没有差别。但是我们要注意Java Runtime在后面到底做了什么。就像注释中标明的。自动包装类在每次循环都会new一个Integer对象,将i赋值到对象中,然后添加到total。在这自动包装类的循环中分配了83个对象(循环100次怎么不是分配了100个对象?我也觉得疑惑,我想这是Java底层为我们做的优化吧)。但是基本类型的循环没有分配对象。
Integer的自动包装类型占用内存16byte大小为int的4倍,这就会产生性能问题。
但是在JAVA提供的集合中我们却不得不使用自动包装类,特别是HashMap,我们只能使用自动包装类。
为解决这个问题Android为我们提供了自己的集合类型来解决这个问题:
- SparseBooleanArray<int,boolean>
- SparseArray<int,obj>
- SparseLongMap<int,long>
- LongSparseMap<long,obj>
- SparseIntArray<int,int>
这些集合类的实现与ArrayMaps一样,具体实现可以进入查看。
怎么查找我们的代码中哪里使用了自动包装呢?我们可以使用AndroidStudio提供的调试工具AllocationTracker和TraceView来查找。