1、final修饰符(关键字)。
1.1被final修饰的类,就意味着不能再派生出新的子类,不能作为父类而被子类继承。因此一个类不能既被abstract声明,又被final声明。
String类就是final类。
1.2 final修饰在变量上,是最后的量值,量值不能修改,所以是常量。
final修饰在成员变量上,必须直接给初值,不给初值是语法错,不是运行错。
final修饰在局部变量上,可以先声明,后给初值,初值只能赋值一次。
比如:
public class Test3 {
private final String S = “final实例变量S”;
private final int A = 100;
public final int B = 90;
public static final int C = 80;
private static final int D = 70;
final double i=8.0; //final double i;是错的
public final int E; //final空白,必须在初始化对象的时候赋初值
//初始化E对象
public Test3(int x) {
E = x;
}
public static void main(String[] args) {
Test3 t = new Test3(2);
//t.A=101; //出错,final变量的值一旦给定就无法改变
//t.B=91; //出错,final变量的值一旦给定就无法改变
//t.C=81; //出错,final变量的值一旦给定就无法改变
//t.D=71; //出错,final变量的值一旦给定就无法改变
System.out.println(t.A);
System.out.println(t.B);
System.out.println(t.C); //不推荐用对象方式访问静态字段
System.out.println(t.D); //不推荐用对象方式访问静态字段
System.out.println(Test3.C);
System.out.println(Test3.D);
//System.out.println(Test3.E); //出错,因为E为final空白,依据不同对象值有所不同.
System.out.println(t.E);
Test3 t1 = new Test3(3);
System.out.println(t1.E); //final空白变量E依据对象的不同而不同
}
public void test1() {
final int a; //final空白,在需要的时候才赋值
final int b = 4; //局部常量–final用于局部变量的情形
final int c; //final空白,一直没有给赋值.
a = 3;
//a=4; 出错,已经给赋过值了.
//b=2; 出错,已经给赋过值了.
}
}
1.3将方法声明为final,那么这个方法就变成最后的方法,被final声明的方法也同样只能使用,是不能重写的(被子类覆盖的),但是可以重载。final不能用于修饰构造方法。
比如:
public class Test2 extends Test1 {
public void f1() {
System.out.println(“Test1中的父类方法f1被覆盖!”);
}
public static void main(String[] args) {
Test2 t = new Test2();
t.f1();
t.f2(); // 调用从父类继承过来的final方法
t.f3(); // 调用从父类继承过来的方法
// t.f4(); //调用失败,无法从父类继承获得私有的
}
}
public class Test1 {
public void f1() {
System.out.println(“父类的f1方法”);
}
// 无法被子类覆盖的方法
public final void f2() {
System.out.println(“父类的f2方法”);
}
public void f3() {
System.out.println(“父类的f3方法”);
}
private void f4() {
System.out.println(“父类的f4方法”);
}
}
1.4当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。
public class Test3 {
public static void main(String[] args) {
new Test3().f1(2);
}
public void f1(final int i) {
//i++; //i是final类型的,值不允许改变的.
System.out.print(i);
}
}
2、finally是在异常处理时提供finally块来执行任何清除操作。不管有没有异常被抛出、捕获,finally块都会被执行。try块中的内容是在无异常时执行到结束。catch块中的内容,是在try块内容发生catch所声明的异常时,跳转到catch块中执行。finally块则是无论异常是否发生,都会执行finally块的内容,所以在代码逻辑中有需要无论发生什么都必须执行的代码,就可以放在finally块中。
2.1当try中有return时执行顺序
return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂存在栈里面,等待finally执行后再返回)
情况一(try中有return,finally中没有return)
“return num += 80”被拆分成了“num = num+80”和“return num”两个语句,线执行try中的“num =num+80”语句,将其保存起来,在try中的”return num“执行前,先将finally中的语句执行完,而后再将90返回。
情况二(try和finally中均有return)
try中的return被”覆盖“掉了,不再执行。
情况三(finally中改变返回值num
虽然在finally中改变了返回值num,但因为finally中没有return该num的值,因此在执行完finally中的语句后,test()函数会得到try中返回的num的值,而try中的num的值依然是程序进入finally代码块前保留下来的值,因此得到的返回值为10。并且函数最后面的return语句不会执行。
另外一种情况:将num的值包装在Num类中
总结如下:
try语句在返回前,将其他所有的操作执行完,保留好要返回的值,而后转入执行finally中的语句,而后分为以下三种情况:
情况一:如果finally中有return语句,则会将try中的return语句”覆盖“掉,直接执行finally中的return语句,得到返回值,这样便无法得到try之前保留好的返回值。
情况二:如果finally中没有return语句,也没有改变要返回值,则执行完finally中的语句后,会接着执行try中的return语句,返回之前保留的值。
情况三:如果finally中没有return语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别,分以下两种情况,:
如果return的数据是基本数据类型,则在finally中对该基本数据的改变不起作用,try中的return语句依然会返回进入finally块之前保留的值。
如果return的数据是引用数据类型,而在finally中对该引用数据类型的属性值的改变起作用,try中的return语句返回的就是在finally中改变后的该属性的值。
3、finalize是方法名,该方法从Object类继承而来。可以告诉垃圾回收器应该执行的操作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。子类可以重写finalize()方法实现对资源的回收。垃圾回收只负责回收内存,并不负责资源的回收,资源回收要由程序员完成,Java虚拟机在垃圾回收之前会先调用垃圾对象的finalize方法用于使对象释放资源(如关闭连接、关闭文件),之后才进行垃圾回收,这个方法一般不会显示的调用,在垃圾回收时垃圾回收器会主动调用,当我们调用System的gc()方法的时候,由垃圾回收器调用finalize(),回收垃圾。
注意,无法确切地保证垃圾回收器何时调用该方法,也无法保证调用不同对象的方法的顺序。即使一个对象包含另一个对象的引用,或者在释放一个对象很久以前就释放了另一个对象,也可能会以任意的顺序调用这两个对象的Finalize方法。如果必须保证采用特定的顺序,则必须提供自己的特有清理方法。