Bootstrap

Android&Java try-catch-finally正确用法

一、try-catch-finally的用途

1、异常捕获;
2、同步锁的应用。

try用于存放要核心代码,catch捕获核心代码发生的异常,finally用于存放那些无论是否出现异常都一定会执行的代码。在实际使用中,通常用于释放锁、数据库连接等资源,把资源释放方法放到 finally 中,可以大大降低程序出错的几率

二、try-catch的正确使用

try{
 // 核心代码,如果读取数据库内容
}catch(Exception e){
 //异常捕获,例如输出异常信息

}finally{
  //善后处理,无论是否异常,都会执行的部分
}

三、奇怪的try-finally (错误的用法)

从代码上看是为了保证锁的释放

public void updateChatMsgReadFlag(long time) {
	mLock.writeLock().lock();
	try {
		if (dataBaseManager != null) {
			dataBaseManager.updateRtChatMsgReadFlag(time);
		}
	} finally {
		mLock.writeLock().unlock();
	}
}



try {
	String sTableName = getChatTableName(mDatabase);
	String sql = "select * from " + sTableName + " where ("
		+ ChatColumns.CHAT_RECEIVEUSERID + "=?" + " or "
		+ ChatColumns.CHAT_SENDUSERID + "=?)" + " and "
		+ ChatColumns.CHAT_TIME + "<?" + " order by "
		+ ChatColumns.CHAT_TIME + " desc limit ?";

	cursor = mDatabase.rawQuery(sql, new String[] { ownerId + "",ownerId + "", timeMillions + "", limit + "" });

	for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
		AbsChatMessage entity = dataToObject(cursor);
		msgList.add(entity);
	}
} finally {
	if (cursor != null) {
		cursor.close();
	}
}

从代码看是保证数据库的cursor得到有效的关闭。

在项目中看到的代码,也不知道小伙伴是怎么想的,就把catch给丢掉,咋一看用了try没有问题,但实际运行中却异常了,异常是自然的,这种坑多数情况下要分析堆栈并结合代码能找出问题,其次利用工具进行codereview,再就是仔细的人工codereview能发现。

四、关于try-catch-finally的面试考察

1、try、catch、finally 考察,请指出下面程序的运行结果。

public class TryDemo {
    public static void main(String[] args) {
        System.out.println(foo());
    }
    public static int foo() {
        try {
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            System.out.print("3");
        }
    }
}

执行结果:31。

相信很多同学应该都做对了,try、catch。finally 的基础用法,在 return 前会先执行 finally 语句块,所以是先输出 finally 里的 3,再输出 return 的 1。

2、try、catch、finally 考察2,请指出下面程序的运行结果。

public class TryDemo {
    public static void main(String[] args) {
        System.out.println(foo1());
    }
    public static int foo1() {
        try {
            return 2;
        } catch (Exception e) {
            return 1;
        } finally {
            return 3;
        }
    }
}

执行结果:3。

这题有点显难,但也不难,try 返回前先执行 finally,结果 finally 里不按套路出牌,直接 return 了,自然也就走不到 try 里面的 return 了。

finally 里面使用 return 仅存在于面试题中,实际开发中千万不要这么用。

3、try、catch、finally 考察3,请指出下面程序的运行结果。

public class TryDemo {
    public static void main(String[] args) {
        System.out.println(test1());
    }
    public static int test1() {
        int i = 0;
        try {
            i = 2;
            return i;
        } catch (Exception e) {
            return 1;
        } finally {
            i = 3;
        }
    }
}

执行结果:2。

这边估计有不少同学会以为结果应该是 3,因为我们知道在 return 前会执行 finally,而 i 在 finally 中被修改为 3 了,那最终返回 i 不是应该为 3 吗?确实很容易这么想,我最初也是这么想的,当初的自己还是太年轻了啊。

这边的根本原因是,在执行 finally 之前,JVM 会先将 i 的结果暂存起来,然后 finally 执行完毕后,会返回之前暂存的结果,而不是返回 i,所以即使这边 i 已经被修改为 3,最终返回的还是之前暂存起来的结果 2。

这边其实根据字节码可以很容易看出来,在进入 finally 之前,JVM 会使用 iload、istore 两个指令,将结果暂存,在最终返回时在通过 iload、ireturn 指令返回暂存的结果。

面试考察部分来自
https://blog.csdn.net/v123411739/article/details/115364158

;