这是一个关于面试观点的重要问题。
final(小写)是java中的保留关键字。我们不能将其用作标识符,因为它是保留的。我们可以在变量、方法和类中使用这个关键字。java中的最后一个关键字具有不同的含义,这取决于它应用于变量、类或方法。
- 带变量的最终版本: 一旦初始化,变量的值就不能更改。
JAVA
class
A {
public
static
void
main(String[] args)
{
// Non final variable
int
a =
5
;
// final variable
final
int
b =
6
;
// modifying the non final variable : Allowed
a++;
// modifying the final variable :
// Immediately gives Compile Time error.
b++;
}
}
如果我们将任何变量声明为final,我们就不能修改它的内容,因为它是final,如果我们修改它,我们就会得到编译时错误。
- 期末课程: 该类不能被子类化。无论何时我们将任何类声明为final,这意味着我们不能扩展该类或该类 无法扩展 或者我们不能把这个类变成子类。
JAVA
final
class
RR {
public
static
void
main(String[] args)
{
int
a =
10
;
}
}
// here gets Compile time error that
// we can't extend RR as it is final.
class
KK
extends
RR {
// more code here with main method
}
- 最终方法: 该方法不能被子类重写。每当我们将任何方法声明为final时,这意味着我们不能重写该方法。
JAVA
class
QQ {
final
void
rr() {}
public
static
void
main(String[] args)
{
}
}
class
MM
extends
QQ {
// Here we get compile time error
// since can't extend rr since it is final.
void
rr() {}
}
注: 如果一个类被声明为final,那么 默认情况下 该类中存在的所有方法都自动为final,但 变量不是 .
JAVA
// Java program to illustrate final keyword
final
class
G {
// by default it is final.
void
h() {}
// by default it is not final.
static
int
j =
30
;
public
static
void
main(String[] args)
{
// See modified contents of variable j.
j =
36
;
System.out.println(j);
}
}
输出 :
36
正如final是一个保留关键字一样,final在java中也是一个保留关键字,也就是说,我们不能将其用作标识符。finally关键字与 试/接住拦网 并保证即使抛出异常,也会执行一段代码。finally块将在try和catch块之后执行,但在控制权转移回原点之前执行。
JAVA
// A Java program to demonstrate finally. class Geek { // A method that throws an exception and has finally. // This method will be called inside try-catch. static void A() { try { System.out.println( "inside A" ); throw new RuntimeException( "demo" ); } finally { System.out.println( "A's finally" ); } } // This method also calls finally. This method // will be called outside try-catch. static void B() { try { System.out.println( "inside B" ); return ; } finally { System.out.println( "B's finally" ); } } public static void main(String args[]) { try { A(); } catch (Exception e) { System.out.println( "Exception caught" ); } B(); } } |
输出:
inside A A's finally Exception caught inside B B's finally
最终可以使用的情况有很多种。以下讨论了以下问题:
- 案例1:程序中不会出现异常
JAVA
// Java program to illustrate finally in
// Case where exceptions do not
// occur in the program
class
B {
public
static
void
main(String[] args)
{
int
k =
55
;
try
{
System.out.println(
"In try block"
);
int
z = k /
55
;
}
catch
(ArithmeticException e) {
System.out.println(
"In catch block"
);
System.out.println(
"Dividing by zero but caught"
);
}
finally
{
System.out.println(
"Executes whether exception occurs or not"
);
}
}
}
输出 :
In try block Executes whether exception occurs or not
在这里,异常不会发生,但仍然会执行finally块,因为finally意味着无论是否发生异常都要执行。 上述程序的流程 :首先,它从main方法开始,然后转到try block和in try,因为没有发生异常,所以流不会转到catch block,因此流直接从try转到finally block。
- 案例2:异常发生,相应的catch块匹配
JAVA
// Java program to illustrate finally in
// Case where exceptions occur
// and match in the program
class
C {
public
static
void
main(String[] args)
{
int
k =
66
;
try
{
System.out.println(
"In try block"
);
int
z = k /
0
;
// Carefully see flow doesn't come here
System.out.println(
"Flow doesn't came here"
);
}
catch
(ArithmeticException e) {
System.out.println(
"In catch block"
);
System.out.println(
"Dividing by zero but caught"
);
}
finally
{
System.out.println(
"Executes whether an exception occurs or not"
);
}
}
}
输出 :
In try block In catch block Dividing by zero but caught Executes whether an exception occurs or not
这里,发生上述异常,并找到相应的catch块,但仍然执行finally块,因为finally意味着执行是否发生异常,或者是否找到相应的catch块。 上述程序的流程 :首先,从main方法开始,然后转到try块,在try中发生算术异常,相应的catch块也可用,因此流转到catch块。在此之后,流不会再次转到try block,因为一旦try block中出现异常,则流 没有 再来试试block。在finally之后,execute因为finally意味着无论是否发生异常,或者是否找到相应的catch块,都要执行。
- 案例3:发生异常,相应的catch块未找到/匹配
JAVA
// Java program to illustrate finally in
// Case where exceptions occur
// and do not match any case in the program
class
D {
public
static
void
main(String[] args)
{
int
k =
15
;
try
{
System.out.println(
"In try block"
);
int
z = k /
0
;
}
catch
(NullPointerException e) {
System.out.println(
"In catch block"
);
System.out.println(
"Dividing by zero but caught"
);
}
finally
{
System.out.println(
"Executes whether an exception occurs or not"
);
}
}
}
输出 :
In try block Executes whether an exception occurs or not Exception in thread "main":java.lang.ArithmeticException: / by zero followed by stack trace.
这里发生上述异常,相应的catch块未找到/匹配,但仍然执行finally块,因为finally意味着执行是否发生异常,或者相应的catch块是否找到/匹配。 上述程序的流程 :首先从main方法开始,然后转到try块,在try中发生算术异常,并创建相应的catch块 不 可供如此流动 没有 去接布洛克。在此之后,流不会再次转到try block,因为一旦try block中出现异常,则流 没有 再来试试block。在finally之后,execute因为finally意味着无论异常是否发生,或者相应的catch块是否找到/匹配,都要执行。
finally block的应用 :所以基本上finally block的用法是 资源释放 。意味着需要关闭在try块中打开的所有资源,例如网络连接、数据库连接,以便在打开时不会丢失资源。所以这些资源需要在最后一个区块关闭。
JAVA
// Java program to illustrate // use of finally block import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; class K { private static final int SIZE = 10 ; public static void main(String[] args) { PrintWriter out = null ; try { System.out.println( "Entered try statement" ); // PrintWriter, FileWriter // are classes in io package out = new PrintWriter( new FileWriter( "OutFile.txt" )); } catch (IOException e) { // Since the FileWriter in // try block can throw IOException } // Following finally block cleans up // and then closes the PrintWriter. finally { if (out != null ) { System.out.println( "Closing PrintWriter" ); out.close(); } else { System.out.println( "PrintWriter not open" ); } } } } |
输出 :
Entered try statement PrintWriter not open
笔记 :finally块是防止资源泄漏的关键工具。关闭文件或以其他方式恢复资源时,请将代码放在finally块中,以确保始终恢复资源。
JDK1.7是如何将finally块的使用作为可选的?
在jdk 1.6 finally block成为英雄之前,建议将其用于资源释放,但从jdk 1.7 finally开始,block现在是可选的(不过您可以使用它)。因为当程序流到达try块的末尾时,我们在try块中打开的资源将自动被释放/关闭。 这种不使用finally块而自动释放资源的概念称为 尝试使用资源声明 .
最终确定方法
这是一个 方法 那 垃圾收集器 总是打电话只是 之前 删除/销毁符合垃圾收集条件的对象,以便执行 清理活动 .清理活动意味着关闭与该对象相关联的资源,如数据库连接、网络连接或资源取消分配。记住是的 不 保留关键字。 一旦finalize方法完成,垃圾收集器就会立即销毁该对象。finalize方法存在于对象类中,其语法为:
protected void finalize throws Throwable{}
由于对象类包含finalize方法,因此finalize方法可用于每个java类,因为对象是所有java类的超类。因为它可用于每个java类,所以垃圾收集器可以在上调用finalize方法 任何java对象 现在,存在于对象类中的finalize方法有一个空的实现,在我们的类中有清理活动,那么我们必须 推翻 这种方法可以定义我们自己的清理活动。
与最终确定方法有关的案例:
- 案例1: 对于符合垃圾收集条件的对象,将执行该对象对应的类finalize方法
JAVA
class
Hello {
public
static
void
main(String[] args)
{
String s =
new
String(
"RR"
);
s =
null
;
// Requesting JVM to call Garbage Collector method
System.gc();
System.out.println(
"Main Completes"
);
}
// Here overriding finalize method
public
void
finalize()
{
System.out.println(
"finalize method overriden"
);
}
}
输出 :
Main Completes
笔记 :此处仅显示上述输出 主要完成 和 不 “finalize method Overrided”,因为垃圾收集器对符合垃圾收集条件的类对象调用finalize方法。在上面我们已经做了-> s=null 而’s’是String类的对象,因此将调用String类finalize方法,而不是我们的类(即Hello类)。所以我们修改代码,比如->
Hello s = new Hello(); s = null;
现在我们的类,即Hello类finalize方法被调用。 输出 :
finalize method overriden Main Completes
所以基本上,垃圾收集器对符合垃圾收集条件的类对象调用finalize方法。所以,如果字符串对象符合垃圾收集的条件,那么 一串 将调用类finalize方法并 不是“你好”课 最后确定方法。
- 案例2: 我们可以显式地调用finalize方法,然后它将像普通方法调用一样执行,但对象不会被删除/销毁
JAVA
class
Bye {
public
static
void
main(String[] args)
{
Bye m =
new
Bye();
// Calling finalize method Explicitly.
m.finalize();
m.finalize();
m =
null
;
// Requesting JVM to call Garbage Collector method
System.gc();
System.out.println(
"Main Completes"
);
}
// Here overriding finalize method
public
void
finalize()
{
System.out.println(
"finalize method overriden"
);
}
}
输出 :
finalize method overriden //call by programmer but object won't gets destroyed. finalize method overriden //call by programmer but object won't gets destroyed. Main Completes finalize method overriden //call by Garbage Collector just before destroying the object.
笔记 :因为finalize是一个方法而不是保留关键字,所以我们可以调用finalize方法 明确地 ,然后它将像普通的方法调用一样执行,但对象不会被删除/销毁。
- 案例3:
- a部分) 如果程序员在执行finalize方法时调用finalize方法,则会出现一些未检查的异常。
JAVA
class
Hi {
public
static
void
main(String[] args)
{
Hi j =
new
Hi();
// Calling finalize method Explicitly.
j.finalize();
j =
null
;
// Requesting JVM to call Garbage Collector method
System.gc();
System.out.println(
"Main Completes"
);
}
// Here overriding finalize method
public
void
finalize()
{
System.out.println(
"finalize method overriden"
);
System.out.println(
10
/
0
);
}
}
输出 :
exception in thread "main" java.lang.ArithmeticException: / by zero followed by stack trace.
所以 重点 is:如果程序员调用finalize方法,在执行finalize方法时,一些未检查的异常会出现,那么JVM会通过出现异常来异常终止程序。所以在这种情况下,程序终止是 不正常的 .
- 第二部分) 如果垃圾收集器在执行finalize方法时调用finalize方法,则会出现一些未检查的异常。
JAVA
class
RR {
public
static
void
main(String[] args)
{
RR q =
new
RR();
q =
null
;
// Requesting JVM to call Garbage Collector method
System.gc();
System.out.println(
"Main Completes"
);
}
// Here overriding finalize method
public
void
finalize()
{
System.out.println(
"finalize method overriden"
);
System.out.println(
10
/
0
);
}
}
输出 :
finalize method overriden Main Completes
所以 重点 is:如果垃圾收集器在执行finalize方法时调用finalize方法,则会出现一些未检查的异常,然后JVM 忽视 该例外和程序的其余部分将正常继续。所以在这种情况下,程序终止是 典型的 而且没有异常。
- a部分) 如果程序员在执行finalize方法时调用finalize方法,则会出现一些未检查的异常。
要点:
- 无法保证调用finalize的时间。在对象没有被引用到任何地方(可能会被垃圾收集)之后,可以随时调用它。
- JVM在执行finalize方法时不会忽略所有异常,但会忽略 只有 未经检查的例外情况 。如果相应的catch块存在,那么JVM将不会忽略并执行相应的catch块。
- 系统gc()只是请求JVM执行垃圾收集器。是否调用垃圾收集器取决于JVM。通常,当堆区域没有足够的可用空间或内存不足时,JVM会调用垃圾收集器。
本文由 拉贾特·拉瓦特和马纳夫 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 贡献极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。