很久以前都想写关于java这仨哥俩的日志,一直拖到现在,还是太懒了~~~
今天是2014年新年,祝大家新年快乐,新的一年也学到更多的专业知识!
小杨在看final的时候想到很多面试的时候面试官都会问:“final ,finally,finalize的区别”
于是怒写一篇博文,给自己,也分享给大家,如有错误之处,敬请指正。
final关键字:声明这是无法改变的。原因:设计或效率
final使用环境:数据,方法和类
【一】数据
不可改变量是有用的,在一些环境下如:
1.一个永不改变的编译时常量——减轻运行时的负担,这些常量必须是基本数据类型,并且以关键字final表示,在定义时还必须对其赋值
- public class TestFinal1 {
- /**
- * public可以被用于包之外
- * 定义static则强调只有一份
- * 定义为final则说明他是一个常量
- * Java规范:既是static又是final域的变量用大写表示,并且字与字之间用下划线分开(
- * 比如你希望定义窗体大小,不希望杯改变/是一张固定的地图)
- */
- private static final int NUMBER_ONE = 5;
- public static int test(){
- return NUMBER_ONE+1;
- }
- public static void main(String[] args){
- //System.out.println(BUNBER++); cannot change this value
- System.out.println(NUMBER_ONE);
- }
- }
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...
新的一年,新的开始~~~~ 大家加油!