关于 Java 中 finally 语句块的深度辨析
- 格式:doc
- 大小:149.50 KB
- 文档页数:14
java的finally⽤法finally作为异常处理的⼀部分,它只能⽤在try/catch语句中,并且附带⼀个语句块,表⽰这段语句最终⼀定会被执⾏(不管有没有抛出异常),经常被⽤在需要释放资源的情况下。
之前在写爬⾍的时候数据库连接的频率很⾼,有时候数据处理的不好,sql报错后,抛出异常但后边的数据库连接没有断开。
导致最后数据库连接数过⼤,不让再连接了(因为是个⼈库,所以直接重启了⼀下)。
这个释放数据库连接的操作就可以⽤finally来进⾏。
⾸先看⼀下没有⽤finally的代码(不能直接运⾏,能看懂什么意思就⾏)Connection conn;Statement stmt;try{ conn = DriverManager.getConnection(url,userName,password); stmt = conn.createStatement; String sql = "sql";//需要执⾏的sql stmt.executeUpdate(sql); stmt.close(); conn.close();}catch(Exception e){ e.printStackTrace();}在程序正常运⾏的时候,没有异常抛出,没有问题。
但在程序抛出异常(sql出错了),try⾥⾯的语句不执⾏了直接被执⾏catch⾥⾯的语句了,就造成了⼀个数据库连接没有正常关闭。
数据量如果⼤起来,数据库的最⼤连接数到达上限,就不再允许创建新的连接了。
然后finally的⽤处现在就能体现出来了Connection conn = null;Statement stmt = null;try { conn = DriverManager.getConnection(url,userName,password); stmt = conn.createStatement; String sql = "sql";//需要执⾏的sql stmt.executeUpdate(sql); stmt.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); }finally{ if(stmt! = NULL){ stmt.close(); } if(conn! = NULL){ conn.close(); } }这样即使sql运⾏出错,抛出了异常,在最后的finally代码中再进⾏⼀次数据库连接的判断,就可以保证数据库连接资源不会被平⽩⽆故的浪费掉。
Java中final、finally、finalize的区别与⽤法1.简单区别:final⽤于声明属性,⽅法和类,分别表⽰属性不可交变,⽅法不可覆盖,类不可继承。
finally是异常处理语句结构的⼀部分,表⽰总是执⾏。
finalize是Object类的⼀个⽅法,在垃圾收集器执⾏的时候会调⽤被回收对象的此⽅法,供垃圾收集时的其他资源回收,例如关闭⽂件等。
2.中等区别:虽然这个单词在Java中都存在,但是并没太多关联:final:java中的关键字,修饰符。
A).如果⼀个类被声明为final,就意味着它不能再派⽣出新的⼦类,不能作为⽗类被继承。
因此,⼀个类不能同时被声明为abstract抽象类的和final的类。
B).如果将变量或者⽅法声明为final,可以保证它们在使⽤中不被改变. 1)被声明为final的变量必须在声明时给定初值,⽽在以后的引⽤中只能读取,不可修改。
2)被声明final的⽅法只能使⽤,不能重载。
finally:java的⼀种异常处理机制。
finally是对Java异常处理模型的最佳补充。
finally结构使代码总会执⾏,⽽不管⽆异常发⽣。
使⽤finally可以维护对象的内部状态,并可以清理⾮内存资源。
特别是在关闭数据库连接这⽅⾯,如果程序员把数据库连接的close()⽅法放到finally中,就会⼤⼤降低程序出错的⼏率。
finalize:Java中的⼀个⽅法名。
Java技术使⽤finalize()⽅法在垃圾收集器将对象从内存中清除出去前,做必要的清理⼯作。
这个⽅法是由垃圾收集器在确定这个对象没被引⽤时对这个对象调⽤的。
它是在Object类中定义的,因此所的类都继承了它。
⼦类覆盖finalize()⽅法以整理系统资源或者执⾏其他清理⼯作。
finalize()⽅法是在垃圾收集器删除对象之前对这个对象调⽤的。
3.详细区别:这是⼀道再经典不过的⾯试题了,我们在各个公司的⾯试题中⼏乎都能看到它的⾝影。
Final可以让你控制你的成员、方法,或者使一个类是否可被覆写或继承等功能,这些特点使final在java中拥有了一个不可或缺的地位,也是学习java 时必须要知道和掌握的关键字之一。
(1)final成员当在类中定义变量时,在其前面加上final关键字,这个变量一旦被初始化便不可改变,不可改变的意思对基本类型来说是其值不可变,而对于对象来说是其引用不可再变。
其初始化可以在两个地方,一是定义处,二是构造函数中。
还有一种用法是定义方法中的参数为final。
对于基本类型的变量,这样做并没有什么实际意思,因为基本类型在调用方法时是传值的,也就是说你可以在方法中更改这个参数变量而不会影响到调用语句,然而对于对象变量,却显得实用,因为对象变量在传递时是传递其引用的,这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量。
当你在方法中不需要改变作为参数的对象变量时。
明确实用final进行声明,会防止你无意的修改而影响到调用方法。
(2)final方法将方法声明为final有两个原因,第一是说明已经知道这个方法提供的功能已经满足要求,不需要进行扩展,并且也不允许任何从此类继承的类来的覆写这个方法,但是继承仍然可以继承这个方法,也就是说可以直接实用。
第二就是允许编译器将所有对此方法的调用转化为inling(行内)调用的机制,它会调用final 方法时,直接将方法主题插入到调用处,而不是进行例行的方法调用,例如保存断点,圧栈等这样可能会使程序效率有所提高。
然而当方法主体非常庞大时,或在多处调用此方法时,调用主体代码便会迅速膨胀,可能反而会影响效率,所以要慎用final进行方法定义(3)final 类当将final用于类身上时,就需要仔细考虑,因为一个final类是无法被任何人继承的,那也就意味着此类在一个继承树中是一个叶子类,冰儿此类的设计已被认为很完美而不需要进行修改或扩展。
对于final类中的成员,可以定义为final,也可以不用final。
try catch finally的用法`try-catch-finally` 是 Java 和其他一些编程语言中的一种错误处理结构。
这种结构用于捕获异常,并确保无论是否发生异常,都能执行某些清理代码。
以下是 `try-catch-finally` 的基本用法:```javatry {// 尝试执行的代码块} catch (ExceptionType1 e) {// 当发生ExceptionType1异常时,将执行此代码块} catch (ExceptionType2 e) {// 当发生ExceptionType2异常时,将执行此代码块} finally {// 无论是否发生异常,都将执行此代码块}````try` 块:包含可能会抛出异常的代码。
`catch` 块:用于捕获并处理特定的异常。
可以有多个 `catch` 块来处理不同类型的异常。
`finally` 块:无论是否发生异常,都会执行此块中的代码。
这可以用于释放资源或执行必要的清理工作。
例子:```javatry {int[] arr = new int[5];arr[10] = 100; // 这将抛出一个ArrayIndexOutOfBoundsException } catch (ArrayIndexOutOfBoundsException e) {("数组越界异常: " + ());} finally {("这是finally块。
");}```在这个例子中,由于数组越界,`try` 块中的代码将抛出一个`ArrayIndexOutOfBoundsException`。
这个异常将被 `catch` 块捕获并打印出一个消息。
无论是否发生异常,`finally` 块都将被执行并打印出 "这是finally块。
"。
final、finally与finalize的区别1. final 在java中,final可以⽤来修饰类,⽅法和变量(成员变量或局部变量)。
下⾯将对其详细介绍。
1.1 修饰类 当⽤final修饰类的时,表明该类不能被其他类所继承。
当我们需要让⼀个类永远不被继承,此时就可以⽤final修饰,但要注意:final类中所有的成员⽅法都会隐式的定义为final⽅法。
1.2 修饰⽅法使⽤final⽅法的原因主要有两个: (1) 把⽅法锁定,以防⽌继承类对其进⾏更改。
(2) 效率,在早期的java版本中,会将final⽅法转为内嵌调⽤。
但若⽅法过于庞⼤,可能在性能上不会有多⼤提升。
因此在最近版本中,不需要final⽅法进⾏这些优化了。
final⽅法意味着“最后的、最终的”含义,即此⽅法不能被重写。
注意:若⽗类中final⽅法的访问权限为private,将导致⼦类中不能直接继承该⽅法,因此,此时可以在⼦类中定义相同⽅法名的函数,此时不会与重写final的⽭盾,⽽是在⼦类中重新地定义了新⽅法。
class A{private final void getName(){}}public class B extends A{public void getName(){}public static void main(String[]args){System.out.println("OK");}}1.3 修饰变量 final成员变量表⽰常量,只能被赋值⼀次,赋值后其值不再改变。
类似于C++中的const。
当final修饰⼀个基本数据类型时,表⽰该基本数据类型的值⼀旦在初始化后便不能发⽣变化;如果final修饰⼀个引⽤类型时,则在对其初始化之后便不能再让其指向其他对象了,但该引⽤所指向的对象的内容是可以发⽣变化的。
本质上是⼀回事,因为引⽤的值是⼀个地址,final要求值,即地址的值不发⽣变化。
try-catch-finally语句的说明
try-catch-finally语句是一种异常处理机制,用于捕获和处理代
码中可能发生的异常。
它由三个部分组成:try、catch和finally。
1. try:try块中包含了可能抛出异常的代码。
如果try块中的代码正常执行,即没有抛出异常,那么将跳过catch块,直接执
行finally块。
但是,如果try块中的代码抛出了异常,那么后
续的代码将不会被执行,而是跳转到catch块。
2. catch:catch块用于捕获和处理try块中抛出的异常。
在
catch块中,可以定义一个或多个catch子句,每个catch子句
处理一种类型的异常。
当捕获到匹配的异常类型时,相应的catch子句将被执行。
如果没有匹配的catch子句,异常将被传
递给上一级调用栈。
3. finally:finally块中的代码无论是否发生异常,都会被执行。
finally块通常用于执行清理操作,例如关闭打开的文件或释放
资源。
即使在try块中使用了return语句来退出方法,finally
块中的代码也会被执行。
总结:try-catch-finally语句允许我们在代码中捕获和处理异常,确保程序的正常执行,在发生异常时执行相应的操作,并在方法返回之前执行必要的清理操作。
finally的用法总结一、finally 的基本语法和作用在编程中,我们经常会遇到需要进行一些清理操作的情况,无论是正常结束还是出现异常。
Python 提供了一个关键字 finally 来处理这种情况。
finally 语句块中的代码无论是否发生异常,它们都将被执行。
finally 的基本语法如下:```pythontry:# 可能发生异常的代码块except ExceptionType:# 异常处理的代码块# 这里可以有多个 except 从句来处理不同类型的异常else:# 如果没有发生异常,执行这个 else 块中的代码finally:# 无论是否发生异常,都会执行这个 finally 块中的代码```其中,try 中包含可能会引发异常的代码块;except 是用来捕获并处理特定类型或所有类型的异常;else 中是当 try 块没有引发任何异常时要执行的代码;finally 中是无论是否有异常都必须执行的清理操作。
二、finally 的应用场景1. 关闭文件或释放资源在进行文件操作或者进行网络请求等资源占用较大的操作时,为了避免资源泄露或占用过久带来负面影响,可以将关闭文件或释放资源等操作放在finally 块中。
这样即使在 try 块中产生了错误或者出现了其他情况导致程序退出,也能够保证资源的正常释放。
示例代码如下:```pythontry:file = open("example.txt", "r")# 对文件进行读取和处理的操作except FileNotFoundError:print("文件不存在!")finally:file.close()```在这个例子中,无论文件是否存在都会执行 finally 块中的 `file.close()` 操作,确保资源被及时释放。
2. 数据库连接的关闭当我们在使用数据库时,打开数据库连接是一个常见的操作。
java中final的原理Java中的final关键字是一个非常重要的关键字,它可以用来修饰类、方法和变量。
final的原理是为了实现不可改变性和不可继承性,从而增强程序的安全性和稳定性。
本文将从不同角度解析final的原理及其在Java中的应用。
1. final修饰类使用final修饰的类是不可继承的,即不能有子类。
这样做的目的是为了防止类的功能被修改或破坏,保证类的稳定性。
final类不能被继承,因此其成员方法也无法被重写,从而保证了类的方法的一致性和安全性。
2. final修饰方法使用final修饰的方法是不可重写的,即子类无法对该方法进行覆盖。
这样做的目的是为了保证方法的功能不被修改,防止误操作或恶意修改,保证程序的正确性和安全性。
3. final修饰变量使用final修饰的变量是不可修改的,即其值在初始化后不能再被修改。
这样做的目的是为了保证变量的值不被修改,确保数据的一致性和安全性。
final修饰的变量必须在声明时或构造函数中进行初始化,之后就不能再修改其值。
4. final的内存模型在Java中,final修饰的变量在内存中有特殊的存储方式。
对于基本类型的final变量,编译器会将其值直接存储在使用该变量的地方,而不是存储在堆或栈中。
对于引用类型的final变量,编译器会将其引用存储在堆中,但不允许修改引用指向的对象。
5. final的使用场景final关键字在Java中有广泛的应用场景。
首先,final修饰的类可以提供不可变的对象,例如String类就是一个final类,保证了字符串的不可变性。
其次,final修饰的方法可以保证方法的功能不被修改,例如Object类中的equals方法就是一个final方法,确保了对象比较的正确性。
最后,final修饰的变量可以提供常量,例如Math类中的PI就是一个final变量,表示圆周率,其值不可修改。
6. final与性能优化final关键字在Java中还可以用于性能优化。
finally语句的使⽤关于try..catch中的final⼦句:package com.javase.Exception;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;/*关于try..catch中的final⼦句:1 在finally字句中的代码是最后执⾏的,并且⼀定会执⾏。
及时try语句块中的代码出现了异常,他也会执⾏。
finally⼦句必须和try⼀起出现,不能单独编写。
2 finally语句通常使⽤在哪些情况下呢?通常在finally语句块中完成资源的释放/关闭。
因为finally中的代码⽐较有保障。
即使try语句块中的代码出现异常,finally中代码也会正常执⾏。
*/public class ExceptionTest10 {public static void main(String[] args) {FileInputStream fls = null;// 声明位置当到try外⾯,这样在finally中才能⽤。
try {// 创建输⼊流对象fls = new FileInputStream("C:\\jetbrains-agent.jar");// 开始读⽂件...//String s = null;// 这⾥⼀定会出现空指针异常!s.toString();// 流使⽤完需要关闭,因为流是占⽤资源的。
// 及时以上程序出现异常,流也必须要关闭。
// 放在这⾥流可能关闭不了fls.close();} catch (FileNotFoundException ex) {ex.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (NullPointerException e){e.printStackTrace();} finally {System.out.println("finally 执⾏啦!");// 流的关闭放在这⾥⽐较保险。
finally的用法一、了解finally关键字的作用与用法在编程领域中,finally是一个常见的关键字。
它通常与try和catch结构一起使用,用于处理异常情况和资源的释放。
在本文中,将探讨finally关键字在不同编程语言中的用法,以及如何正确使用它来优化代码。
二、finally的基本语法无论try块是否出现异常,finally块中的代码都会被执行。
finally块位于try-catch语句的末尾,并且是可选的。
下面以Java为例,具体说明finally的基本语法:```try {// 可能出现异常的代码} catch(Exception e) {// 异常处理逻辑} finally {// 无论是否出现异常都会执行的代码}```三、为什么要使用finally?1. 保证资源释放:有些操作可能会涉及到打开文件、数据库连接等需要手动关闭或释放资源的情况。
如果没有正确地处理这些资源,在发生异常时可能导致资源泄露及其他问题。
2. 提供清理机会:有些情况下,在try块中执行完一系列操作后,不管是否抛出异常,需要进行额外的操作或清理工作。
比如关闭网络连接、删除临时文件等。
3. 确保最终执行:即使在catch块内部抛出新异常或在try块中使用了return语句,finally块中的代码也会被执行。
这样可以确保最终要执行的逻辑得到执行,避免因为异常或提前返回而导致未完成的操作。
四、finally关键字的具体应用过程1. 释放资源:利用finally关键字可以确保资源被正确释放。
例如,在Java中打开文件读取数据时,可能会出现文件无法打开等异常情况。
通过在finally块中关闭文件流,即使出现异常,也能够保证文件锁定和资源释放。
2. 数据库连接管理:在数据库相关操作中,通常需要手动建立数据库连接,并且必须在使用完毕后关闭连接。
如果不正确处理异常或手动关闭连接,则可能导致数据库连接池耗尽或造成性能问题。
3. 清理工作:有时候需要进行一些清理工作来确保系统正常运行。
关于Java 中finally 语句块的深度辨析乍看这个题目,是不是有人会问,这个谁不知道啊,大凡熟悉Java 编程的人都知道finally 语句块的作用和用法。
有什么可深度辨析的呢?事实并非如此,我发现即使写了很多年Java 程序的人,也不一定能够透彻的理解finally 语句块。
本篇将以生动形象的案例来带您由浅入深的来分析一下这个小小的finally,希望这篇文章能够让您真正的理解finally 语句块的本质,至少阅读完本篇文章后,没有觉得浪费了时间。
可不能小看这个简单的 finally,看似简单的问题背后,却隐藏了无数的玄机。
接下来我就带您一步一步的揭开这个finally 的神秘面纱。
问题分析首先来问大家一个问题:finally 语句块一定会执行吗?很多人都认为finally 语句块是肯定要执行的,其中也包括一些很有经验的Java 程序员。
可惜并不像大多人所认为的那样,对于这个问题,答案当然是否定的,我们先来看下面这个例子。
清单 1.public class Test {public static void main(String[] args) {System.out.println("return value of test(): " + test());}public static int test() {int i = 1;// if(i == 1)// return 0;System.out.println("the previous statement of try block");i = i / 0;try {System.out.println("try block");return i;}finally {System.out.println("finally block");}}}清单1 的执行结果如下:the previous statement of try blockException in thread "main" ng.ArithmeticException: / by zeroat com.bj.charlie.Test.test(Test.java:15)at com.bj.charlie.Test.main(Test.java:6)另外,如果去掉上例中被注释的两条语句前的注释符,执行结果则是:return value of test(): 0在以上两种情况下,finally 语句块都没有执行,说明什么问题呢?只有与finally 相对应的try 语句块得到执行的情况下,finally 语句块才会执行。
以上两种情况,都是在try 语句块之前返回(return)或者抛出异常,所以try 对应的finally 语句块没有执行。
那好,即使与finally 相对应的try 语句块得到执行的情况下,finally 语句块一定会执行吗?不好意思,这次可能又让大家失望了,答案仍然是否定的。
请看下面这个例子(清单2)。
清单 2.public class Test {public static void main(String[] args) {System.out.println("return value of test(): " + test());}public static int test() {int i = 1;try {System.out.println("try block");System.exit(0);return i;}finally {System.out.println("finally block");}}}清单2 的执行结果如下:try blockfinally 语句块还是没有执行,为什么呢?因为我们在try 语句块中执行了System.exit (0) 语句,终止了Java 虚拟机的运行。
那有人说了,在一般的Java 应用中基本上是不会调用这个System.exit(0) 方法的。
OK !没有问题,我们不调用System.exit(0) 这个方法,那么 finally 语句块就一定会执行吗?再一次让大家失望了,答案还是否定的。
当一个线程在执行try 语句块或者catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的finally 语句块可能不会执行。
还有更极端的情况,就是在线程运行try 语句块或者catch语句块时,突然死机或者断电,finally 语句块肯定不会执行了。
可能有人认为死机、断电这些理由有些强词夺理,没有关系,我们只是为了说明这个问题。
回页首finally 语句剖析说了这么多,还是让我们拿出些有说服力的证据吧!还有什么证据比官方的文档更具说服力呢?让我们来看看官方网站上的《The Java Tutorials》中是怎样来描述 finally 语句块的吧!以下位于**** 之间的内容原封不动的摘自于《The Java Tutorials 》文档。
*******************************************************************************The finally BlockThe finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return,continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.Note:If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.*******************************************************************************请仔细阅读并认真体会一下以上两段英文,当你真正的理解了这两段英文的确切含义,你就可以非常自信的来回答“finally 语句块是否一定会执行?”这样的问题。
看来,大多时候,并不是Java 语言本身有多么高深,而是我们忽略了对基础知识的深入理解。
接下来,我们看一下 finally 语句块是怎样执行的。
在排除了以上 finally 语句块不执行的情况后,finally 语句块就得保证要执行,既然 finally 语句块一定要执行,那么它和try 语句块与 catch 语句块的执行顺序又是怎样的呢?还有,如果try 语句块中有return 语句,那么 finally 语句块是在return 之前执行,还是在return 之后执行呢?带着这样一些问题,我们还是以具体的案例来讲解。
关于try、catch、finally 的执行顺序问题,我们还是来看看权威的论述吧!以下**** 之间的内容摘自Java 语言规范第四版(《The Java™ P rogramming Language, Fourth Edition》)中对于try,catch,和 finally 的描述。
*******************************************************************************12.4. Try, catch, and finallyY ou catch exceptions by enclosing code in Try blocks. The basic syntax for a T ry block is:try {statements} catch (exception_type1 identifier1) {statements} catch (exception_type2 identifier2) {statements...} finally {statements}where either at least one catch clause, or the finally clause, must be present. The body of the try statement is executed until either an exception is thrown or the body finishes successfully. If an exception is thrown, each catch clause is examined in turn, from first to last, to see whether the type of the exception object is assignable to the type declared in the catch. When an assignable catch clause is found, its block is executed with its identifier set toreference the exception object. No other catch clause will be executed. Any number of catch clauses, including zero, can be associated with a particular TRy as long as each clause catches a different type of exception. If no appropriate catch is found, the exception percolates out of the try statement into any outer try that might have a catch clause to handle it.If a finally clause is present with a try, its code is executed after all other processing in the try is complete. This happens no matter how completion was achieved, whether normally, through an exception, or through a control flow statement such as return or break.*******************************************************************************上面这段文字的大体意思是说,不管try 语句块正常结束还是异常结束,finally 语句块是保证要执行的。