`
xiaoheliushuiya
  • 浏览: 399931 次
文章分类
社区版块
存档分类
最新评论

【初学者常见问题】浅谈final,finally,finalize()

 
阅读更多

很久以前都想写关于java这仨哥俩的日志,一直拖到现在,还是太懒了~~~

今天是2014年新年,祝大家新年快乐,新的一年也学到更多的专业知识!大笑

小杨在看final的时候想到很多面试的时候面试官都会问:“final ,finally,finalize的区别”

于是怒写一篇博文,给自己,也分享给大家,如有错误之处,敬请指正。

final关键字:声明这是无法改变的。原因:设计或效率

final使用环境:数据,方法和类

【一】数据

不可改变量是有用的,在一些环境下如:

1.一个永不改变的编译时常量——减轻运行时的负担,这些常量必须是基本数据类型,并且以关键字final表示,在定义时还必须对其赋值

  1. publicclassTestFinal1{
  2. /**
  3. *public可以被用于包之外
  4. *定义static则强调只有一份
  5. *定义为final则说明他是一个常量
  6. *Java规范:既是static又是final域的变量用大写表示,并且字与字之间用下划线分开(
  7. *比如你希望定义窗体大小,不希望杯改变/是一张固定的地图)
  8. */
  9. privatestaticfinalintNUMBER_ONE=5;
  10. publicstaticinttest(){
  11. returnNUMBER_ONE+1;
  12. }
  13. publicstaticvoidmain(String[]args){
  14. //System.out.println(BUNBER++);cannotchangethisvalue
  15. System.out.println(NUMBER_ONE);
  16. }
  17. }

2.一个在运行时初始化的值,而你不希望它改变(通常和static关键字搭配),这里可以用一个测试程序来说明有无static将导致变量初始化是否赋值的问题,如果没有static,就可以不用初始化,如果有static,就必须给变量初始化

public class TestFinal2{
	/* if not have the key of static,could not assignment to n
	   public final int n;
	   public TestFinal2(int n){
		   System.out.println(n);
		   this.n = n;
	   }
	   public static void main(String args[]){
		  TestFinal2 t = new TestFinal(2);
	   }
	*/

	//if have this key of static,must initialize n
	public static final int n = 2;
	public TestFinal2(){
		System.out.println(n);
	}
	public static void main(String args[]){
		TestFinal2 t = new TestFinal2();
	}
}

说明:一个既是static又是final的域只占据一段不能改变的存储空间

如果一个static域不是final的,那么在它访问时,总是要求在它被读取之前要进行承接(为这个域分配存储空间)和初始化(初始化改存储空间)

【二】方法

方法的修饰也可以用于final,但是不能被子类所覆盖。

public class TestFinal{
	public TestFinal(){
		test2();
	}
	//can not be overrided
	public static final void test(){
		System.out.println("This is TestFinal test method");
	}
	public static void test2(){
		test();
	}
	public static void main(String args[]){
		TestFinal tf = new TestFinal();
		TestBaseFinal tbf = new TestBaseFinal();
	}
}
class TestBaseFinal extends TestFinal{
	public TestBaseFinal(){
		test2();
	}
	public static void test2(){
		System.out.println("This is TestBaseFinal test mehtod");
	}
}


final参数(用作方法里对参数的修饰):Java允许在参数列表中以声明的方式将参数指明为final,这意味着你无法在方法中更改参数引用所指向的对象。

【三】类

当某个类定义为final时,出于某种考虑,你对该类的设计永不需要做任何变动,或出于安全考虑,你不希望它有子类。

最后final在处理并发的时候和安全访问方面有着一定作用,可以使相应变量和对象成为不可变对象,这样就减少了加锁同步带来的性能消耗,这方面我还在阅读Java并发相关的材料,扩充自己这方面的知识储备。

讲到finalize()就必须要讲到java垃圾回收机制方面的知识。

垃圾回收:

(1)对象可能不被垃圾回收

(2)垃圾回收并不等于析构

(3)垃圾回收只与内存有关

自适应的垃圾回收技术:

a.停止——复杂

b.复制

c.标记——清扫

d.分代收集

JIT(Just—In—Time)编译器技术

(1)第一种让编译器编译所有代码

(2)第二种惰性评估(新版JDK,hotspot采用此技术):编译器在必要的时候才编译代码

Joshua bloch 在《Effective Java》提出“终结函数无法预料,常常是危险的,总之是多余的,但是我想既然它存在,就一定的作用。翻阅了深入理解JAVA虚拟机对finalize又有了一个新的认识。

finalize()方法是对象自我拯救的唯一机会,这个就类似于坐牢一样,如果牢里面还不知错认改,就要被XX.....对象在被GC(garbage collection)回收时有一次自我拯救的机会,如果出现以下两种情况的话就会被直接回收:1.对象没有覆盖finalize方法,2.虚拟机已经调用了finalize方法。

下面是一个例子来描述对象的自我拯救(摘自深入理解Java虚拟机——ZZM)

//try not use finalize()
public class FinalizeEscapeGC{

	public static FinalizeEscapeGC SAVE_HOOK = null;

	//if the object is alive?
	public void isALive(){
		System.out.println("yes i am alive");
	}
	@Override
	protected void finalize() throws Throwable{
		super.finalize();
		System.out.println("finalize method executed£¡");
		FinalizeEscapeGC.SAVE_HOOK = this;
	}
	public static void main(String args[]) throws Throwable{
		SAVE_HOOK = new FinalizeEscapeGC();

		//self-redemption first
		SAVE_HOOK = null;
		System.gc();
		//finalize() priority is very low,if not this sentence,will fault.
		Thread.sleep(500);
		if(SAVE_HOOK!=null){
			SAVE_HOOK.isALive();
		}else{
			System.out.println("no,i am dead");
		}
		//self-redemtion second
		SAVE_HOOK = null;
		System.gc();
		//finalize() priority is very low,if not this sentence,will fault.
		Thread.sleep(500);
		if(SAVE_HOOK!=null){
			SAVE_HOOK.isALive();
		}else{
			System.out.println("no,i am dead");
		}
	}
}
最后输出:
finalize method executed!
yes i am alive
no,i am dead
第一次调用了finalize(),第二次就自动被垃圾回收机制回收了。。。

finally:定义在try,catch后或与break,return使用都会被执行

使用环境:当要把除内存之外的资源恢复到它们的初始状态时,就要用到finally子句,很多时候我们要在最后作相应的处理,比如流的关闭,连接数据库的关闭(JDBC通常会用到)通常都是在finally关键字里进行。

下面是一个简单的测试,这里其实有一个知识点:到底是return和finally的执行关系。

public class TestFinally{
	public static int test(int a){
		if(a<3){
			try{
				switch(a){
					case 1:
						System.out.println(1);
						return 1;
					case 2:
						System.out.println(2);
						return 2;
					default:
						System.out.println(0);
						return 0;
				}
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				System.out.println("finally...");
			}
		}
		return a;
	}
	public static void main(String args[]){
		test(1);
	}
}

运行结果:
1
finally...

新的一年,新的开始~~~~ 大家加油!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics