在Java中完成final、finally和finalize

这是一个关于面试观点的重要问题。

null

最终关键字

final(小写)是java中的保留关键字。我们不能将其用作标识符,因为它是保留的。我们可以在变量、方法和类中使用这个关键字。java中的最后一个关键字具有不同的含义,这取决于它应用于变量、类或方法。

  1. 带变量的最终版本: 一旦初始化,变量的值就不能更改。

    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,如果我们修改它,我们就会得到编译时错误。

  2. 期末课程: 该类不能被子类化。无论何时我们将任何类声明为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
    }

    
    

  3. 最终方法: 该方法不能被子类重写。每当我们将任何方法声明为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. 案例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. 案例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. 案例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. 案例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. 案例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. 案例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 忽视 该例外和程序的其余部分将正常继续。所以在这种情况下,程序终止是 典型的 而且没有异常。

要点:

  • 无法保证调用finalize的时间。在对象没有被引用到任何地方(可能会被垃圾收集)之后,可以随时调用它。
  • JVM在执行finalize方法时不会忽略所有异常,但会忽略 只有 未经检查的例外情况 。如果相应的catch块存在,那么JVM将不会忽略并执行相应的catch块。
  • 系统gc()只是请求JVM执行垃圾收集器。是否调用垃圾收集器取决于JVM。通常,当堆区域没有足够的可用空间或内存不足时,JVM会调用垃圾收集器。

    本文由 拉贾特·拉瓦特和马纳夫 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 贡献极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。

    如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享