概述
简介:
“final、finally和finalize有什么区别?”, 这是一道再经典不过的面试题了,我们在各个公司的面试题中几乎都能看到它的身影。final、finally和finalize虽然看起来很像,含义也差不多(字根都是final),但是它们的用法是不同的。本节主要来讨论一下它们在实际场景中的运用。
final用法说明:
是java关键字之一,用于修饰类或者方法,或者变量,可以和static共存。
被fianl修饰的这些类,方法,变量都不能再被修改。对于类,不能再被继承;对于方法,不能被重写;对于基本类型的变量,不能修改其值(其实就是常量);
对于引用类型(即final修饰的是一个对象的情形),就表示这个变量被赋予的引用是不可变的,注意,不可改变的只是这个变量所保存的引用,并不是这个引用所指向的对象。
一个类不能既被abstract声明,又被final声明,这是因为被final修饰的类,就意味着不能再派生出新的子类,不能作为父类而被子类继承,这和abstract正好是互斥的。
被final修饰的变量必须被初始化。初始化方式:
在定义的时候初始化。
final变量可以在初始化块中初始化,不可以在静态初始化块中初始化。
静态final变量可以在静态初始化块中初始化,不可以在初始化块中初始化。
final变量还可以在类的构造器中初始化,但是静态final变量不可以。
final用来修饰一个变量:
程序举例:
package demo.test.my;
public class BydCar {
// 非静态final变量在定义时初始化
public final String tagName = "BydCar";
//非静态final变量可以在静态初始化块中初始化
public final int tagId;
// 在初始化块中初始化
{
tagId = 10000;
}
// 非静态final变量不能在静态初始化块中初始化
// public final int C;
// static {
// C = 30;
// }
// 静态常量,在定义时初始化
public static final float Min_Value = 0;
public static final float Max_Value;
// 静态常量,在静态初始化块中初始化
static {
Max_Value = 200.0f;
}
// 静态变量不能在初始化块中初始化
// public static final int Max_Value;
// {
// Max_Value = 200.0f;
// }
//非静态final变量可以在构造器中初始化
public final int code;
// 静态final变量不可以在构造器中初始化
// public static final int code;
// 在构造器中初始化
public BydCar() {
code = 666666; //非静态final变量可以在构造器中初始化
// 静态final变量不可以在构造器中初始化
// code = 777777;
// 给final的变量第二次赋值时,编译会报错
//code = 888888; //Variable 'G' might already have been assigned to
}
// final变量未被初始化,编译时就会报错
//public final int I; //编译错误:Variable 'I' might not have been initialized
// 静态final变量未被初始化,编译时就会报错
//public static final int STATIC_J; //编译错误: Variable 'STATIC_J' might not have been initialized
}
运行上面的代码之后出了可以发现final变量(常量)和静态final变量(静态常量)未被初始化时,编译会报错;
另外还可以发现,静态final变量可以在构造器中初始化,却不可以在初始化块中初始化。
final用来修饰一个方法:
程序举例:
BaseClass.java:
package demo.test.my;
public class BaseClass {
//
public final void fun() {
System.out.println("[BaseClass] fun be call!");
}
}
SubClass.java:继承自BaseClass
package demo.test.my;
public class SubClass extends BaseClass {
/**
* 子类无法重写(override)父类的final方法fun,否则编译时会报错:
* 'fun()' cannot override 'fun()' in 'demo.test.my.BaseClass'; overridden method is final
*/
// public void fun() {
// System.out.println("[SubClass]子类--重写final方法");
// }
public static void main(String[] args) {
SubClass sc = new SubClass();
sc.fun(); //调用弗雷的fun
}
}
运行结果:
[BaseClass] fun be call!
这里需要特殊说明的是,具有private访问权限的方法也可以增加final修饰,但是由于子类无法继承private方法,因此也无法重写它。
finally的用法:
finally是java的关键字,用在try-catch-finally,最终被执行的代码放在finally语句块中。
注意,return、continue和break都无法阻止finally语句块的执行。
finally的代码示例:
package demo.test.my;
public final class F0Car {
public static void main(String[] args) {
try {
throw new NullPointerException();
} catch (NullPointerException e) {
System.out.println("程序抛出了异常");
return;
} finally {
System.out.println("执行了finally语句块");
}
}
}
运行结果:
程序抛出了异常
执行了finally语句块
finalize的用法:
finalize不是java关键字,而是一个方法,属于java.lang.Object类的一个方法,它的定义如下:
protected void finalize() throws Throwable { }
finalize()方法是在GC清理它所从属的对象时被JVM自动调用的,如果执行它的过程中抛出了无法捕获的异常(uncaught exception),GC将终止对改对象的清理,并且该异常会被忽略;直到下一次GC开始清理这个对象时,它的finalize()会被再次调用。
finalize的代码示例:
package demo.test.my;
public final class F0Car {
// 重写finalize()方法
protected void finalize() throws Throwable {
System.out.println("F0Car::finalize()"); //输出:F0Car::finalize()
}
public static void main(String[] args) {
F0Car car = new F0Car();
car = null;
System.gc();
}
}
运行结果:
F0Car::finalize()
分析:
程序调用了java.lang.System类的gc()方法,引起GC的执行,GC在清理ft对象时调用了它的finalize()方法,因此才有了上面的输出结果。调用System.gc()等同于调用下面这行代码:
Runtime.getRuntime().gc();
调用它们的作用只是建议垃圾收集器(GC)启动,清理无用的对象释放内存空间,但是GC的启动并不是一定的,这由JAVA虚拟机来决定。
最后
以上就是无情鸡翅为你收集整理的Java中final、finally和finalize的区别的全部内容,希望文章能够帮你解决Java中final、finally和finalize的区别所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复