final关键字
先看看final关键字,它能够被用于如下几个地方:
一、修饰属性、局部变量、方法参数:
若是final修饰的是一个基本类型,就表示这个变量所赋予的值不可修改,即它是个常量;若是final修饰的是一个对象,就表示这个变量被赋予的引用不可修改(但咱们能够修改该引用所指向对象里的内容,这里所说的不可修改是指final修改的引用一但指向了谁,就不能再指向别的对象了)。下面来看看修改属性与变量时须要注意的几点:
在方法中定义的内部类只能访问方法中的final类型的局部变量,由于用final定义的局部变量是一个常量,运行时不是放在栈里的,所以它的生命同期超出了方法运行的生命周期:
编程
//final不能去掉,不然编译通不过 spa
public Comparable f(final Comparable o1) { 指针
return new Comparable() { orm
public int compareTo(Object o2) { 对象
return o1.compareTo(o2); blog
} 继承
}; 接口
} 生命周期
final修改的静态属性,必须在声明的同时或者在静态块中初始化;final修饰的非静态属性,必须在声明的同时、或非静态块中或者是构造函数中初始化:
public class A {
private final int a = 1;//非静态属性在定义时初始化
private final static int b = 1;//静态属性在定义时初始化
private final int c;//非静态属性在定义时未初始化
{
//非静态属性在非静态块中初始化
c = 1; (对)
}
private final static int d;//静态属性在定义时未初始化
static {
//静态属性在静态块中初始化
d = 1; (对)
}
private final int e;//非静态属性在定义时未初始化
A() {
//非静态属性在构造函数中初始化
e = 1; (对)
}
}
静态属性不能在非静态块中初始化(由于非静态块是在new时才调用,而静态属性在对象尚未建立时也能使用(静态属性在类加载的时候进行了初始化));
非静态属性不能在静态块中(由于在静态块中不能访问非静态属性、变量及方法)初始化,能够在非静态块或构造函数中初始化
public class A {
private final int a;//!! 非静态属性未初始化
private final static int b;//!! 静态属性未初始化
private final int c;
static {
//!! 非静态属性不能在静态块中初始化
c = 1; (错)
}
private final static int d;
{
//!! 静态属性不能在非静态块中初始化
d = 1; (错)
}
private final static int e;
A() {
//!! 静态属性不能在构造函数中初始化
e = 1; (错)
}
}
接口中的属性成员默认就是 public final static,只能在定义时就初始化:方法默认是public abstract
package A;
public interface A {
//接口中的属性成员默认就是 public final static
int i = 1;
// !! 接口中的访问修饰符只能是 public (Illegal modifier for the interface field idd.a; only public, static & final are permitted) ,但可不写
//protected int a = 1; (错)
// !! 接口中的属性只能在定义时就初始化
// public static final int b; (错)
public static final int b=0; (对)
// !! 接口中的属性是常量,不能在静态块与非静态块中初始化,由于接口中不能有静态块与非静态块
// (错) static{
// b=1;
// }
// (错) {
// b=1;
// }
// 接口中方法的访问修饰符只能是 public (Illegal modifier for the interface method ssss; only public & abstract are permitted) ,但可不写
// public void ssss();
}
package B;
import A.A;
public class B {
public static void main(String[] args) {
// !! 不能修改,由于接口中的定义的属性默认就是final
//A.i = 2; (错)
//接口中的定义的属性默认就是public final static,由于能够被不一样包静态访问
System.out.println(A.i);
}
}
这里提到了静态区与非静态区,它们的区别是,静态区在类装载时执行一次,而非静态区每在实例化一个对象时就执行一次:
public class A {
static {
System.out.println("static block");
}
{
System.out.println("block");
}
public static void main(String[] args) {
new A();
new A();
}
/* output:
static block
block
block
*/
}
另外,用final修饰的变量会有更高的效率,若是一个变量不在变化时,那么它就应该定义成常量,因此在须要的地方咱们尽可能使用常量,由于这样在编译时期就能肯定。
二、修饰方法:
被final修改的方法不能被覆写。
class A {
public final void f() {}
}
class B extends A {
// !! 不能覆写final方法
// public void f() {} (错)
// public final void f() {} (错)
}
private方法默认就是final方法,编译器在处理private方法时,是按照final方法来对待的,这样能够提升该方法被调用时的效率。
三、修饰类
final类不容许被继承(若是String类),编译器在处理时把它的全部方法都看成final的(但数据成员既能够是final,也能够不是,以定义时前面修饰为准),所以final类比普通类拥有更高的效率:
final class A {
//注,final中的属性能够是final,也能够不是,以定义时前面修饰为准
int i = 1;
public final void f() {}
//final类中的全部方法默认就是final方法
void m() {}
}
// !! final 类不能继承
//class B extends A {}
public class C {
public static void main(String[] args) {
A a = new A();
a.i = 2;//能够修改final类的非final属性成员
}
}
接口与抽象类不能用final来修饰,即final interface、final abstract class是不容许的:
// !! 接口不能用final来修饰
public final interface A {} (错)
// !! 抽象类不能用final来修饰
public final abstract class A {} (错)
finally关键字
finally关键字用在try/catch语句最末,表示不论是否抛出异常,finally块中的语句最终确定、必定会被执行,执行的顺序为 try块 —> finally块(不抛异常状况下)或 try块 —> catch块(抛异常状况下)—> finally块 :
try {//不抛异常状况下
System.out.println("try");
}
catch (Exception e) {
System.out.println("catch");
}
finally {
System.out.println("finally");
}
System.out.println("last");
/* output:
try
finally
last
*/
try {//抛异常状况下
System.out.println("try");
throw new NullPointerException();
}
catch (NullPointerException e) {
System.out.println("catch");
throw e;//再次抛出
}
finally {
//不论是try块仍是catch块里抛异常,finally块最后必定会执行
System.out.println("finally");
}
// System.out.println("finally"); (错) 编译不经过;由于有了catch里有了throw e;//catch里再次抛出异常后,不能在finally后面再写了,若是没有在catch里再抛出异常就能够
结果:
/* output:
try
catch
finally
*/
下面看看try、catch、finally有return语句时,到底从哪里返回:
class A {
public static void main(String[] args) {
System.out.println(A.f1());//3
System.out.println(A.f2());//2
try {
System.out.println(A.f3());//方法异常结束
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println(A.f4());//1
System.out.println(A.f5());//4
try {
System.out.println(A.f6());//方法异常结束
}
catch (Exception e) {
e.printStackTrace();
}
}
/*
* 若是 finally 块中有 return 语句,则忽略 try、catch 块中的retrun ,
* 但 finally 中有return不是一种好的编程方式,这样会引发编译时警告
*/
public static int f1() {
System.out.println("--f1()--");
try {
System.out.println("f1 - 1");
nullExcp();//抛空指针异常
return 1;
}
catch (NullPointerException e) { 没执行)
System.out.println("f1 - 2");
return 2;
}
finally {
System.out.println("f1 - 3");
return 3;//从这里返回
}
/*
* !! 这里不能有语句,由于方法在此前已从finally块中返回,或者finally 块中已抛
* 异常后方法结束,但要注意的是,无论catch块中是否抛异常,最会执行finally块
*/
// return 4;
}
/*
* 若是 finally 块中没有 return 语句,但 try、catch 块中有时,若是try中不抛
* 异常,则从try语句块中正常返回,若是try中抛出异常,则从catch块中正常返回或者
* catch抛出异常时方法异常结束
*/
public static int f2() {
System.out.println("--f2()--");
try {
System.out.println("f1 - 1");
nullExcp();//抛空指针异常
return 1;
}
catch (NullPointerException e) {
System.out.println("f1 - 2");
return 2;//从这里返回
}
finally {
System.out.println("f1 - 3");
}
/*
* !! 这里也不能有其余语句了,由于到此方法已经正常或异常结束了
*/
// return 4;
}
//try与catch块都抛异常,最后方法在执行完finally块后从catch块中异常结束
public static int f3() {
System.out.println("--f3()--");
try {
System.out.println("f1 - 1");
nullExcp();//抛空指针异常
return 1;
}
catch (NullPointerException e) {
System.out.println("f1 - 2");
nullExcp();//抛空指针异常,从这里方法异常结束
return 2;
}
finally {
System.out.println("f1 - 3");
}
/*
* !! 这里也不能有其余语句了,由于到此方法已经正常或异常结束了
*/
// return 4;
}
//这是咱们一般写法,只在try或最后返回结果:正常从try中返回
public static int f4() {
System.out.println("--f4()--");
try {
System.out.println("f1 - 1");
return 1;//从这里返回
}
catch (NullPointerException e) {
System.out.println("f1 - 2");
}
finally {
System.out.println("f1 - 3");
}
return 4;
}
//这是咱们一般写法,只在try或最后返回结果:异常后从最后返回
public static int f5() {
System.out.println("--f5()--");
try {
System.out.println("f1 - 1");
nullExcp();//抛空指针异常
return 1;
}
catch (NullPointerException e) {
System.out.println("f1 - 2");
}
finally {
System.out.println("f1 - 3");
}
return 4;//从这里返回
}
public static int f6() {
System.out.println("--f6()--");
try {
System.out.println("f1 - 1");
nullExcp();//抛空指针异常
return 1;
}
catch (NullPointerException e) {
System.out.println("f1 - 2");
nullExcp();//抛空指针异常,从这里方法异常结束
}
finally {
System.out.println("f1 - 3");
}
return 4;
}
private static void nullExcp() {
throw new NullPointerException();
}
}
从上面例子能够看出return语句是不会阻止finally块执行的,那么continue和break可否阻止?答案是不会的,与return同样,finally语句块是在循环被跳过(continue)和中断(break)以前被执行的:
class A {
public static void main(String[] args) {
int i = 0;
System.out.println("--continue--");
while (i++ <= 1) {
try {
System.out.println("i=" + i);
continue;
}
catch (Exception e) {
e.printStackTrace();
}
finally {
System.out.println("finally");
}
}
System.out.println("--break--");
while (i++ <= 3) {
try {
System.out.println("i=" + i);
break;
}
catch (Exception e) {
e.printStackTrace();
}
finally {
System.out.println("finally2");
}
}
}
}
结果:
--continue--
i=1
finally
i=2
finally
--break--
i=4
finally2
finalize关键字
finalize()是Object类的一个方法,finalize()方法是GC(garbage collector)运行机制的一部分,由对象的垃圾回收器调用此方法,当一个对象被回收时,finalize()方法将会被调用。但咱们要注意的是,若是 finalize 方法抛出未捕获的异常,那么该异常将被忽略,而且该对象的终结操做将终止:
protected void finalize() throws Throwable {
System.out.println("finalize");
}
public static void main(String[] args) {
A a = new A();
a = null;
//加快GC回收,但不必定立刻执行加收动做,由虚拟机决定
System.gc();
}
参考原文地址:http://jiangzhengjun.iteye.com/blog/577045