final 关键字的使用

final 可以用来修饰类,方法,变量。意思是“最终的,不可变的”。


修饰variable
final修饰的variable只能被初始化一次!匿名内部类使用的外部局部变量必须用final修饰,是为了保持“数据的一致性”,final修饰的变量只能被初始化一次,正好满足这个需求。
常和static一起使用,该variable用作常量,大写
public static final int COUNT = 10;
member final variable必须在声明时或者构造方法内初始化。在声明时未被初始化的变量称为空白final变量,之后必须在构造方法内初始化,可用来不同对象赋不同的值。
local final variable 必须在声明时初始化


匿名类中要访问外部的变量,则外部变量必须是final的。
匿名内部类访问的外部局部变量需要被final修饰,访问的外部类的成员变量则不需要。(内部类保存了外部类实例的引用,内部类对成员变量的任何修改都会反映到外部类实例本身上,member variable改变了内部类也能拿到它最新的值)
public class MyApplication {
static int memberFiled = 2;
public static void main(String[] args) {
final int local1 = 3;
final int local2 = 5;
Print p = new Print() {

@Override
public void print() {
// TODO Auto-generated method stub
System.out.println(local1);
System.out.println(local2);
System.out.println(memberFiled);
}
};
p.print();
}
}


interface Print{
void print();
}


member varialbe 的生命周期和enclosing object的一样,所以内部类可以引用它,而local variable只在方法被调用时才有效,内部类copy了local variable,如果允许local variable可以改变,那内部类拿到的copy值就和真实的值不一样了,所以为了避免此类前后不一致,编译器就不允许内部类使用的local variable可更改。编译器copy 了 local variable的值通过内部类的构造方法将其传进去。
 "hey, remember it gets copied into the inner class, so if you could change it afterwards, then you get a severe
 inconsistency. So you can't change it, and we're clear with that."
总结:
匿名内部类引用的variab是否会不一致,member variable 不会,为避免local variable导致的不一致,final处理。
生命周期的问题,local variable会随着方法执行结束而失效,而匿名内部类中的代码一般会被其他线程在其他时间执
行,为了保证“到时”该local variable还可用,需要final下,(也即final local variable 会被一直保存?到什么时候?
member variable 的生命周期呢?) 结果:final 和生命周期没有关系!
普通member variable的生命周期:对象创建 到 对象被销毁
local variable 的生命周期:方法调用,变量入栈,方法执行结束,变量出栈
匿名内部类使用外部局部变量,会保持对那个变量的引用,即使外部方法结束,由于内部类还有那个变量对象的引
用,GC也不会回收它。(这句话应该是有问题的,因为如果是引用了外部局部变量的话,那就用不着final了,而因为是copy了一份同样的值,为了内外一致,该copy的值不能被改变了,所以用final修饰,(没有更好的办法吗,如果我就想修改外部局部变量的值呢?))


下面的例子说明了:t 被final修饰,那在本次调用中只被初始化一次,而每次调用都会创建新的对象 t
public class Main {  
      
    public void finalTestFunc() {  
        final FinalTest t = new FinalTest();  
        System.out.println("T:" + t.toString());  
    }  
  
    /** 
     * @param args 
     */  
    public static void main(String[] args) {  
        Main m = new Main();  
        m.finalTestFunc();  
        m.finalTestFunc();  
    }  
  

结果:
final_.A@110003
final_.A@17e4ca






final variable在多线程环境下,即使没有synchronization也可以被安全访问。
接口中的所有变量都隐式的是final的。
当一个集合的引用是final时,意味着该引用不能再被修改,但其中的元素可修改

final List<Integer> its = new ArrayList<Integer>();
its.add(1); //valid
its.add(2);//valid
its.remove(1);//valid
its = new Vector<Integer>();//not valid






修饰method
final修饰的方法,可以被继承当不能被覆盖重写。
当不希望某个方法的意义或实现被继承者修改时,可用final方法。
final方法比非final方法快,因为在运行时不需要被resolved,在编译时已被绑定好了。


修饰class
final修饰的类,不可以被继承,所以相对于其中的方法都是final的,final类中的成员变量如果没有被final修饰,仍然是可以改变的。
当不希望某类的意义或实现被继承者修改时,可用final类。
final类
final class FF{
final int i;
int j;

public FF(int i){
this.i = i;
}

public void setJ(int j){
this.j = j;
}

public int getJ(){
return this.j;
}

int getI(){
return this.i;
}

void f(){
System.out.println("say hello");
}
}


调用
FF f = new FF(3);
f.f();
System.out.println(f.getI());
f.setJ(5);
System.out.println(f.getJ());
f.setJ(6);
System.out.println(f.getJ());


结果:
say hello
3
5
6








----------------------------
与finally,finalize()区分
finally是在处理异常时使用,不管之前正常执行try中的内容还是发生异常执行catch中内容,之后都会执行finally中的内容。即使try中有return语句,也还是会执行finally语句块。

int p(){  
try {
System.out.println("try");
return 5;
} catch (Exception e) {
// TODO: handle exception
}finally{
System.out.println("try");
return 3; //p()返回的结果是3,而不是5
}
}


finalize()方法是当垃圾回收器回收某个不再被引用的对象时,执行的方法,用于释放资源等操作。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值