finally

一、使用finally避免内存泄漏

由于Java支持垃圾回收机制,为此,如果函数正常结束或异常而被迫退出,该函数所创建的所有对象会被自动回收,但是对于Socket或File资源必须要执行清理操作,以便资源回收。如果不对这些资源进行回收,那么就会出现内存泄漏。

public void reclaimResource() throws IOException{
    ServerSocket server = new ServerSocket(5566);
    Socket socket = null;
    try{
	socket = server.accept();
	//业务代码.....
			
    }finally{
	if(null != socket)
	    socket.close();//回收资源 
	if(null != server)
	    server.close();//回收资源
	}
    }
}

二、不要在finally块中处理返回值


public class FinallyTest {
	//把一个字符串转换为整数
public static int getNumber(String str) 
	      throws NumberFormatException {
	try {
	    int number = Integer.parseInt(str);
	    return number; //1
	} catch (NumberFormatException ex) {
	    throw ex;  //2
	} finally {
            return -1; //3
	}
    }
//测试客户端
public static void main(String[] args) {
	try {
	    int ret1 = getNumber("abc"); //4
	    int ret2 = getNumber("123"); //5
	    System.out.println("ret1=" + ret1 + ";ret2=" + ret2);
	} catch (Exception ex) {
	    ex.printStackTrace();
	}
    }

答案揭晓: ret1=-1;ret2=-1


问题1:覆盖了try子句中的返回值


当执行代码2中的//4语句时,在getNumber函数中会产生一个NumberFormatException的异常,catch块在捕捉到该异常后直接抛出,之后的代码执行到了finally代码块,就会重置返回值为-1。

当执行代码2中的//5语句时,在getNumber函数中不会产生异常,会继续执行try代码块中的//1语句,但是此时函数并不会马上返回,之后的代码会执行到finally代码块,仍重置返回值为-1。


问题2:屏蔽了异常


当执行代码2中的//4语句时,明明抛出了异常,为什么在main函数中却捕捉不到了?

在异常代码块中,代码中加上try代码块就标志JVM运行到该语句时会有一个Throwable线程监视该方法运行,若出现异常,则交由异常逻辑处理,如代码2中就会登记当前的异常类型为NumberFormatException;接着执行器会执行finally代码块,会重新给方法运行状态赋值,按照如上finally的业务代码,也就是告诉调用者“该方法执行正确,没有产生异常,返回值为1”。于是,异常就这样消失了。


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
思考:输出的值是什么?

public class FinallyTest {
    static class Color {
	private String name;
	public Color(String nm) {
	    this.name = nm;
	}
	public String getName() {
	    return this.name;
	}
	public void setName(String nm) {
	    this.name = nm;
	}
    }

    public static Color getColor() {
	Color color = new Color("Red");
	try {
	    return color;
	} catch (Exception ex) {
	} finally {
	    color.setName("Black"); 
	}
	    return color;
    }

    // 测试客户端
    public static void main(String[] args) {
	Color color = getColor();
	System.out.println(color.getName());
    }
}

答案是:Black


*因为前面提到try块并没有直接返回,而是执行了finally块中的语句,然后再返回。


1.按照我们程序员的惯性认知:当遇到return语句的时候,执行函数会立刻返回。但是,在Java语言中,如果存在finally就会有例外。除了return语句,try代码块中的break或continue语句也可能使控制权进入finally代码块。
2.请勿在try代码块中调用return、break或continue语句。万一无法避免,一定要确保finally的存在不会改变函数的返回值。
3.函数返回值有两种类型:值类型与对象引用。对于对象引用,要特别小心,如果在finally代码块中对函数返回的对象成员属性进行了修改,即使不在finally块中显式调用return语句,这个修改也会作用于返回值上。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


补充:不要在循环里写try/catch,要将循环写在try/catch块中。

在启用JIT编译器的情形下两种方式生成的bytecode是几乎相同的,执行时间并没有什么不同。但是一旦将JVM的JIT关闭后,两者的bytecode差异很大,第二种方式执行效率会更高些。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值