基础篇-final, finally, finalize 的区别

要知道三者的区别,首先对三者进行简单的认识

一、final

首先明确final是java的关键字,是一种修饰符,可以修饰类、属性、方法。

1、修饰类

使用final修饰的类不能被其他类继承,即抽象类可能永远和final说bye bye 了。

那么都有哪些类被final修饰?

常见的就是java.lang.String以及java.lang包下的多数类。个人觉得被final修饰的这些类主要是直白的实现了一些功能而不再需要我们再继续扩展的一些类。

public final class Boolean
public final class Byte
public final class Character
public static final class Character.UnicodeBlock
public final class Class<T>
public final class Compiler
public final class Double
public final class Integer
public final class StringBuffer
public final class System
...

 

上面可以看到使用final修饰以后无法继承。

如果确定类不会被继承可以使用该修饰符修饰,反之谨慎使用吧

2、修饰方法

/**
 * final关键字用法
 * @author andim
 *
 */
public class FinalDemo extends Test{
	public void test(){
		method();
	}
	/**
	 * 继承的重写不起作用
	 */
	public void method(){
		System.out.println("重写失败,错误提示:Cannot override the final method from Test");
	}
}

class Test{
	public final void method(){
		
	}
}

 

总结:修饰方法主要为了防止外部修改其方法,使用场景多在继承时。

注:类的private方法会隐式地被指定为final方法。

3、修饰属性

修饰变量的场景一般较多

对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。(下面的方法中赋值都会提示错误)

public class FinalDemo{
	public final int in = 5;
	private Object obj = new Object();
	protected String str;//默认赋值为null
	public static void main(String[] args) {
		in = 2;
		obj = new Object();
		str = "string";
	}
}

1.类的成员变量中使用final修饰后的区别

public class FinalDemo{
	public static void main(String[] args) {
		String a = "helloworld";
		final String b = "hello";
		String c = "hello";
		String d = b+"world";
		String e = c+"world";
		System.out.println(d == a);
		System.out.println(e == a);
	}
}

打印结果:

true
false
分析原因:

成员变量a赋值后,helloworld值存入常量区。

因为当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。

所以在构建d时,直接将hello字符串拿到并发现常量池中有该字符串,所以指向其地址。

而c字符串在常量池的新开辟内存地址,所以构建e时是该地址之上的构建,并不指向a的地址空间,所以结果这样。

不过final修饰的成员变量必须在编译时就确定,如果不确定则结果也为false,如给b赋值是使用方法等。

public class FinalDemo{
	String a = "helloworld";
	final String b;
	String c = "hello";
	public FinalDemo(){
		b = "hello";
	}
	public void test(){
		String d = b+"world";
		String e = c+"world";
		System.out.println(d == a);
		System.out.println(e == a);
	}
	public static void main(String[] args) {
		new FinalDemo().test();
	}
}

2.final修饰的引用变量内容是否可变?

public class FinalDemo{
	public static void main(String[] args) {
		final Test test = new Test();
		System.out.println(test.in);
		System.out.println(++test.in);
	}
}

class Test{
	public int in = 0;
}

结果:

0
1
发现是可变的。

3.静态内部类访问外部属性,为什么外部属性必须使用final修饰?

内部类里面使用外部类的局部变量时,其实就是内部类的对象在使用它,内部类对象生命周期中都可能调用它,而内部类试图访问外部方法中的局部变量时,外部方法的局部变量很可能已经不存在了,那么就得延续其生命,拷贝到内部类中,而拷贝会带来不一致性,从而需要使用final声明保证一致性。说白了,内部类会自动拷贝外部变量的引用,为了避免:1. 外部方法修改引用,而导致内部类得到的引用值不一致 2.内部类修改引用,而导致外部方法的参数值在修改前和修改后不一致。于是就用 final 来让该引用不可改变。

好了,final的介绍到此为止,下面看令两个。

 

 

二、finally

finally是在异常处理时提供finally块来执行任何清除操作。不管有没有异常被抛出、捕获,finally块都会被执行。try块中的内容是在无异常时执行到结束。catch块中的内容,是在try块内容发生catch所声明的异常时,跳转到catch块中执行。finally块则是无论异常是否发生,都会执行finally块的内容,所以在代码逻辑中有需要无论发生什么都必须执行的代码,就可以放在finally块中。

所以就是说finally只在捕获异常时使用。

三、finalize

finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
使用finalize还需要注意一个事,调用super.finalize();

一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。
所以,推荐不要使用finalize()方法,它跟析构函数不一样。

1.object定义
protected void finalize() //定义为子类可见

2.执行时机不可预知
当一个对象变得不可触及时,垃圾回收器某个时期会回收此对象。
当回收对象之前会调用finalize方法,这类似于人类临终之前必须做一件事情:写遗言。
因为GC是不确定性的(这跟JVM相关),所以finalize方法的执行具有不可预知性。

3.finalize忽略异常
即finalize代码中若出现异常,异常会被忽略

4.finalize使用
什么时候使用?一般来说,finalize被作为第二种安全网来使用,如FileInputStream类,
当对象回收时,有可能资源为释放,所以这里第二次来确认(那也总比不释放强吧,虽然具体释放时机未定)

总结:

以上三个除了单词长相上相似以外,貌似没有任何有交集的地方

final是修饰符,finally用来捕获异常时无论结果到要执行的代码块,finalize是方法,调用gc的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值