Android问题篇之异常处理(十)

129 阅读3分钟

异常处理

空指针:NullPointException

  1. 对方法参数判空后再使用
  • 例:网络请求返回脏数据
  1. 外部接口调用时,确保返回值不为空,不抛异常
  • 例:页面跳转选择文件,返回时未选择文件
  1. 全局变量的使用,发生内存回收时,全局变量会置为空,使用时注意处理
  • 例:app切至后台,过段时间再切回前台
  1. 调用对象方法属性时确保该对象不为null
  2. 使用Kotlin空安全机制

java中null扩展

  1. null是Java的关键字,是Java中引用类型的默认值
  2. null既不是对象,也不是一种类型,是特殊值,可将其赋值给任何引用类型,也可将其强转为任何引用类型
  3. 可赋值给引用变量和基本类型包装对象,但不可赋值给基本类型,否则会编译报错;赋值给基本类型包装对象编译不会报错,但运行时会抛出NPE(Java自动拆装箱)
  4. 不能使用值为null的引用类型调用其非静态方法,但可调用其静态方法(静态方法使用静态绑定,编译时已决定,即不会抛NPE)
  5. 可使用 ==!= 运算符,不可使用其他运算符(<>等)

越界问题:IndexOutOfBoundsException、StringIndexOutOfBoundsException、ArrayIndexOutOfBoundsException、CursorIndexOutOfBoundsException

  1. 遍历数组或集合时,判断其是否为null或长度是否大于0
  2. 使用数组或集合时,下标是否在0 ~ size-1
  3. 字符串截取时也要判断其下标

类型转换异常:ClassCastException、NumberFormatException、UnknownFormatConversionException

  1. 使用对象时做类型判断
  • if (classA is ClassA) doSomething()
  1. 数字字符类型转换时try-catch捕获,异常时赋默认值
  • try { val x = "123x".toInt() } catch (e: NumberFormatException) { val x = 0 }
  1. 使用String.format()字符串输出时,任何未明确定义为转换的字符都是非法的,例%d、%s、%b...,若使用%需使用双%(%%)

数组声明异常:NegativeArraySizeException

  1. 数组声明时动态设置长度,确保其长度大于等于0(等于0无意义但不会报错)
  • val array = FloatArray(temp.size - 1)

同步修改异常:ConcurrentModificationException

  1. 遍历集合时同步删除集合中元素出现该异常
  • 增强for遍历调用itr.next,ArrayList.remove修改modCount,但未同步修改Itr.expectedModCount,即抛出该异常
  • 可使用迭代器的remove方法,同步修改modCount与expectedModCount解决
  1. 多线程同时操作集合,一个删除,一个追加
  • 可使用线程安全集合处理CopyOnWriteArrayList
  1. 逆序遍历删除

四大组件相关异常

  1. 未注册在AndroidManifest文件中
  2. 非Activity的context启动Activity,未指定FLAG_ACTIVITY_NEW_TASK
  3. Fragment未Attach至Activity时调用resource等方法,需先调用isAdded判断是否已添加再调用
  4. Intent传输数据过大(大于1M)

序列化相关异常

  1. 序列化类中包含未实现序列化的对象,未序列化对象不为null时
class O
class Test(val o: O): Serializable {}
  1. 序列化时未指定ClassLoader,Android中有framework、apk ClassLoaderframework 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())
	}
}
  1. 混淆导致序列化类在反序列化时找不到,此时须在proGuard文件中keep序列化类