可能忽略的Java基础知识 - 理解内部类和匿名内部类,异常与异常捕获

Android开发中经常会用到内部类和异常处理,如果忽略一些基础知识,可能导致内存泄露,有时无法理解一些东西,比如在使用proguard中的类的keep。
内部类和匿名内部类
1.概念
内部类:《Java编程思想》中,“可以将一个类的定义放在另一个类的定义内部,这就是内部类”
匿名内部类(anonymous class),我的理解就是没有主动去命名的内部类
嵌套类:将内部类声明为static的
可以看看java编程思想阅读笔记(四)接口与内部类

2.容易忽略的细节
(1)链接到外部类:
在一个类中使用其内部类时,简单方便,内部类可以访问其所在外围类的所有成员,也就是 外围类名.this 来链接到外部对象的引用上,或者说是持有了其外围类的this对象。在Activity中创建非主线程的Handler,或者通过匿名内部类创建线程使用时,很可能你的Activity已退出,但线程依旧在执行,而且它所持有的Activity对象也依然被引用,导致始终无法被回收。Service也一样,那么有在Activity或Service中这样写么:

new Thread(new Runnable() {

    @Override
    public void run() {
        // do something
    }
}).start();

当内部类为嵌套类,也就是声明为static时,则不持有对外部类的this对象,也就不存在泄露问题。当然,你也别专门在嵌套类中声明一个对象保存外部类对象,说是方便调用外部类的方法(非要这样也可以,记得恰当的时机置null)。
(2)内部类的class文件
一般会知道一个java类文件编译后,对应一个.class文件,那么一个包含内部类的java文件编译后,内部有几个类声明呢?
其实还是一个,内部类以:外部类名$内部类名的形式,在同包中生成了另一个class文件。因此在AndroidManifest文件中,如果想声明的组件是内部类,就会出现外部类名$内部类名的形式;而且在proguard的配置文件中,会看到如下一些语句:

-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

异常与异常捕获
1.概念
Java标准异常的基类为Throwable,表示可作为异常被抛出的类。主要划分为Error和Exception两类,Error表示系统严重问题,一般也不去捕获的问题;Exception则为可被捕获和处理的异常基本类型;两者都是Throwable的直接子类。
Exception又分为运行时异常RuntimeException和非运行时异常,非运行时异常需要try-cath包围

2.可能忽略的问题
(1)catch的Exception是有顺序的
经常会看到如下的try-catch语句

try {
    // http
    // do something
} catch (ClientProtocolException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}

而继承关系是ClientProtocolException -> IOException -> Exception,在catch到IOException,就不会再调用Exception的处理逻辑,因此,其顺序是不能随意变化的,而且编译器也不会同意
(2)恰当的使用try-catch-finally
合理的使用finally,保证资源的回收,如访问ContentProvider中的数据

Cursor cursor = null;
try {

    cursor = getApplicationContext().getContentResolver().query(uri, projection,
            selection, selectionArgs, sortOrder);
    // use cursor
} catch (Exception e) {
    // catch your exception
} finally {
    if (cursor != null) {
        cursor.close();
    }
}

保证在使用cursor过程中出现异常时,也能保证cursor的close。
(3)finally在return语句执行前执行,finally中的return语句会使异常丢失
具体可以自己测试,参看 深入理解java异常处理机制

转载请注明出处:http://blog.csdn.net/w7849516230,欢迎关注微信公众号“编程阳光”

猜你喜欢

转载自blog.csdn.net/w7849516230/article/details/51487296