异常处理
空指针:NullPointException
- 对方法参数判空后再使用
- 外部接口调用时,确保返回值不为空,不抛异常
- 全局变量的使用,发生内存回收时,全局变量会置为空,使用时注意处理
- 调用对象方法属性时确保该对象不为null
- 使用Kotlin空安全机制
java中null扩展
- null是Java的关键字,是Java中引用类型的默认值
- null既不是对象,也不是一种类型,是
特殊值,可将其赋值给任何引用类型,也可将其强转为任何引用类型
- 可赋值给引用变量和基本类型包装对象,但不可赋值给基本类型,否则会编译报错;赋值给基本类型包装对象编译不会报错,但运行时会抛出NPE(Java自动拆装箱)
- 不能使用值为null的引用类型调用其非静态方法,但可调用其静态方法(静态方法使用静态绑定,编译时已决定,即不会抛NPE)
- 可使用
== 或 != 运算符,不可使用其他运算符(<、>等)
越界问题:IndexOutOfBoundsException、StringIndexOutOfBoundsException、ArrayIndexOutOfBoundsException、CursorIndexOutOfBoundsException
- 遍历数组或集合时,判断其是否为null或长度是否大于0
- 使用数组或集合时,下标是否在
0 ~ size-1
- 字符串截取时也要判断其下标
类型转换异常:ClassCastException、NumberFormatException、UnknownFormatConversionException
- 使用对象时做类型判断
- if (classA is ClassA) doSomething()
- 数字字符类型转换时try-catch捕获,异常时赋默认值
- try { val x = "123x".toInt() } catch (e: NumberFormatException) { val x = 0 }
- 使用String.format()字符串输出时,任何未明确定义为转换的字符都是非法的,例%d、%s、%b...,若使用%需使用双%(%%)
数组声明异常:NegativeArraySizeException
- 数组声明时动态设置长度,确保其长度大于等于0(等于0无意义但不会报错)
- val array = FloatArray(temp.size - 1)
同步修改异常:ConcurrentModificationException
- 遍历集合时同步删除集合中元素出现该异常
- 增强for遍历调用itr.next,ArrayList.remove修改modCount,但未同步修改Itr.expectedModCount,即抛出该异常
- 可使用迭代器的remove方法,同步修改modCount与expectedModCount解决
- 多线程同时操作集合,一个删除,一个追加
- 可使用线程安全集合处理CopyOnWriteArrayList
- 逆序遍历删除
四大组件相关异常
- 未注册在AndroidManifest文件中
- 非Activity的context启动Activity,未指定FLAG_ACTIVITY_NEW_TASK
- Fragment未Attach至Activity时调用resource等方法,需先调用isAdded判断是否已添加再调用
- Intent传输数据过大(大于1M)
序列化相关异常
- 序列化类中包含未实现序列化的对象,未序列化对象不为null时
class O
class Test(val o: O): Serializable {}
- 序列化时未指定ClassLoader,Android中有
framework、apk ClassLoader,framework ClassLoader知道如何加载系统内部类,apk ClassLoader知道如何加载自己写的类及系统内部类,默认使用apk ClassLoader,但在系统内存不足时应用被回收重启,此时默认ClassLoader变为framework ClassLoader,即出现找不到类异常ClassNotFoundException
class O implements Parcelable { }
class Test implements Parcelable {
private O o;
...
private Test(Parcel in) {
...
in.readParcelable(O.class.getClassLoader())
}
}
- 混淆导致序列化类在反序列化时找不到,此时须在
proGuard文件中keep序列化类