final、finally、finalize 的区别

final、finally、finalize 的区别

  1. final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,被其修饰的类不可继承。
  2. finally:异常处理语句结构的一部分,表示总是执行。
  3. finalize:Object 类的一个方法,在垃圾回收器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。该方法更像是一个对象生命周期的临终方法,当该方法被系统调用则代表该对象即将“死亡”,但是需要注意的是,我们主动行为上去调用该方法并不会导致该对象“死亡”,这是一个被动的方法(其实就是回调方法),不需要我们调用。

final类中所有的成员方法都会隐式的定义为final方法

final成员变量表示常量,只能被赋值一次,赋值后其值不再改变。类似于C++中的const
当final修饰一个基本数据类型时,表示该基本数据类型的值一旦在初始化后便不能发生变化;如果final修饰一个引用类型时,则在对其初始化之后便不能再指向其他对象,但该引用所指向的对象的内容是可以发生变化的。

  1. finall
    final修饰一个成员变量(属性),必须要显示初始化。有两种初始化方式,(1)变量声明的时候初始化;(2)在变量所在的类的构造函数中对变量赋初值。
    在java中,String被设计成final类,那为什么平时使用时,String的值可以被改变呢?
      字符串常量池是java堆内存中一个特殊的存储区域,当我们建立一个String对象时,假设常量池不存在该字符串,则创建一个,若存在则直接引用已经存在的字符串。当我们对String对象值改变的时候,例如 String a=“A”; a=“B” 。a是String对象的一个引用(我们这里所说的String对象其实是指字符串常量),当a=“B”执行时,并不是原本String对象(“A”)发生改变,而是创建一个新的对象(“B”),令a引用它。

  2. finally
      finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。(×)(这句话其实存在一定的问题)
    很多人都认为finally语句块一定会执行,但真的是这样么?答案是否定的,例如下面这个例子:
    在这里插入图片描述
    当我们去掉注释的三行语句,执行结果为:
    在这里插入图片描述
       为什么在以上两种情况下都没有执行finally语句呢,说明什么问题?
    只有与finally对应的try语句块得到执行的情况下,finally语句块才会执行。以上两种情况在执行try语句块之前已经返回或抛出异常,所以try对应的finally语句并没有执行。
    但是,在某些情况下,即使try语句执行了,finally语句也不一定执行。例如以下情况:
    在这里插入图片描述
      finally 语句块还是没有执行,为什么呢?因为我们在 try 语句块中执行了 System.exit (0) 语句,终止了 Java 虚拟机的运行。那有人说了,在一般的 Java 应用中基本上是不会调用这个 System.exit(0) 方法的。OK !没有问题,我们不调用 System.exit(0) 这个方法,那么 finally 语句块就一定会执行吗?
      再一次让大家失望了,答案还是否定的。当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的 finally 语句块可能不会执行。还有更极端的情况,就是在线程运行 try 语句块或者 catch 语句块时,突然死机或者断电,finally 语句块肯定不会执行了。可能有人认为死机、断电这些理由有些强词夺理,没有关系,我们只是为了说明这个问题。
    易错点:在try-catch-finally语句中执行return语句。我们看如下代码:
    在这里插入图片描述
      答案:4,4,4 。 为什么呢?
      首先finally语句在改代码中一定会执行,从运行结果来看,每次return的结果都是4(即finally语句),仿佛其他return语句被屏蔽掉了。
      事实也确实如此,因为finally用法特殊,所以会撤销之前的return语句,继续执行最后的finally块中的代码。

  3. finalize  
    finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
    特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
      使用finalize还需要注意一个事,调用super.finalize();
      一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样

参考链接 https://www.cnblogs.com/ktao/p/8586966.html

展开阅读全文

没有更多推荐了,返回首页