final、finally、finalize分析

一、final修饰符

1、final修饰变量

2、final修饰方法

3、final修饰类


1、final修饰变量:

当在类中定义变量时,在其前面加上final关键字,这个变量一旦被初始化便不可改变,即不可以被再次赋值,这里的不可改变的意思对基本类型来说

是其值不可变,而对于对象变量来说是其引用不可在变。

问:使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
答:使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。例如,对于如下语句:
   final StringBuffer a=new StringBuffer("immutable");
执行如下语句将报告编译期错误:
  a=new StringBuffer(""); //这里多了一个new,说明引用变量a已经被重新创建了。
但是,执行如下语句则可以通过编译:
  a.append(" broken!"); 
  
  有人在定义方法的参数时,可能想采用如下形式来阻止方法内部修改传进来的参数对象:
   public void method(final StringBuffer param){
   }
  实际上,这是办不到的,在该方法内部仍然可以增加如下代码来修改参数对象:
   param.append("a");

被final修饰的实例变量必须显式指定初始值,只能在如下3个位置指定初始值:

(1)定义final实例变量时指定初始值

(2)在非静态初始化块中为final实例变量指定初始值

(3)在构造器中为final实例变量指定初始值

下面的代码体现了上面的初始化形式:

package programmer;

public class FinalTest1 {
	final int var1 = 1; // 定义final实例变量时指定初始值
	final int var2;
	final int var3;
	{
		var2 = 2; // 在非静态初始化块中为final实例变量指定初始值
	}

	public FinalTest1() {
		this.var3 = 3; // 在构造器中为final实例变量指定初始值
	}

	public static void main(String[] args) {
		FinalTest1 ft1 = new FinalTest1();
		System.out.println("var1:" + ft1.var1);
		System.out.println("var2:" + ft1.var2);
		System.out.println("var3:" + ft1.var3);
	}
}

对于被final修饰的 类变量,同样必须显式指定初始值,而且final类变量只能在2个地方指定初始值:

(1)定义final类变量时指定初始值

(2)在静态初始化块中为final类变量指定初始值

下面也给出相应的初始化代码:

package programmer;

public class FinalTest2 {
	final static int var1 = 1;  //定义final类变量时指定初始值
	final static int var2;
	static {
		var2 = 2;  //在静态初始化块中为final类变量指定初始值
	}

	public static void main(String[] args) {
		System.out.println(FinalTest2.var1);
		System.out.println(FinalTest2.var2);
	}
}

也可以在方法体里面定义final变量,但是要求还是一样的,一样要被显式地赋值,且被赋值之后,以后再也不能对final局部变量重新赋值。

final修饰的变量的初始值其实在编译时就已经确定下来了,所以运行时不可以更改它的值。

下面看几个程序:

package programmer;

public class FinalTest3 {
	public static void main(String[] args) {
		String s1 = "helloworld";
		String s2 = "hello" + "world";
		System.out.println(s1 == s2);
		String s11 = "hello";
		String s22 = "world";
		String s3 = s11 + s22;
		System.out.println(s1 == s3);
	}
}
运行结果如下:


package programmer;

public class FinalTest4 {
	final String s1;
	final String s2;
	final String s3 = "hello";
	{
		s1 = "hello";
	}

	public FinalTest4() {
		s2 = "hello";
	}

	public void display() {
		System.out.println(s1 + s1 == "hellohello");
		System.out.println(s2 + s2 == "hellohello");
		System.out.println(s3 + s3 == "hellohello");
	}

	public static void main(String[] args) {
		FinalTest4 ft4 = new FinalTest4();
		ft4.display();
	}
}
运行结果如下:


package programmer;

public class FinalTest5 {
	final static String s1;
	final static String s2 = "hello";
	static {
		s1 = "hello";
	}

	public static void main(String[] args) {
		System.out.println(s1 + s1 == "hellohello");
		System.out.println(s2 + s2 == "hellohello");
	}
}
运行结果如下:



从上面上个程序我们可以很明显的看出来,java在编译时是无法计算出s1+s2类似的式子的,只有到运行时才可以计算出来,而判断也正好在运行时进行,所以类似s1+s1=="hellohello"是无法判断它是正确的,但是“hello"+"hello"=="hellohello“则是可以的,因为这个式子可以在编译时做相关的优化。

对于final修饰的变量,只有在定义final变量的时候指定初始值才可以当作”编译时优化“,否则无法当成”编译时“优化”。


2、final修饰方法:

当final修饰某个方法,则此方法不可被它的子类重写。

将方法声明为final有如下两个原因:

(1)已经知道这个方法提供的功能已经满足要求,不需要进行扩展,并且也不允许任何从此类继承的类来重写这个方法,但是继承子类仍然可以继承这个方法,可以直接使用。

(2)允许编译器将所有的对此方法的调用转化为inline(行内)调用的机制,它会在调用final方法时,直接将方法主体插入到调用处。这样会使程序效率有所提高。

package programmer;

public class FinalTest6 {
	public static void main(String[] args) {
		FinalInvoke fi = new FinalInvoke();
		fi.info();
	}
}

class FinalInvoke {
	final void info() {
		System.out.println("This is final method!");
	}
}
上面的代码显示了性质(1).


3、final修饰类:

当使用final修饰类时,要仔细考虑,因为一个final类是无法被任何类继承的,那就意味着此类在一个继承树中是一个叶子类,并且此类的设计已经被认为很完美不需要进行修改或者扩展。对于final类中的成员,可以定义为final,也可以不是final,而对于方法,由于所属为final的关系,自然也就成了final型方法。

注意:在任何内部类中访问局部变量都应该使用final修饰。


二、finally:

finally关键字是对Java异常处理模型的最佳补充,finally结构使代码总会执行,不管有无异常发生,使用finally可以维护对象的内部状态,并可以清理非内存资源,如果没有finally,你的代码看起来很费解。


三、finalize:

finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值