final:用于声明属性, 方法和类,分别表示属性不可变、方法不可覆盖、被其修饰的类不可继承。
finally:异常处理语句结构的一部分,表示总是执行。
finalize:Object 类的一个方法,在垃圾回收器执行的时候会调用被回收对象的finalize()方法。JVM不保证此方法总被调用。
举例:
修改被final修饰的属性nickName
public class Student{ public static void main(String[] args) { final String nickName ="Jack"; nickName = "Jack Ma"; } }
运行结果
Error:(27, 5) java: 无法为最终变量nickName分配值
由此说明被final 修饰的属性是不可变的。
那么,final 修饰的方法setName()是否可以被重写呢?
class Person { private String name; public final void setName(String name){ this.name = name; } } public class Student extends Person{ // 重写被final 修饰的setName()方法 public void setName(String name){ System.out.println(name); } }
运行结果
Error:(27, 15) java: Student中的setName(java.lang.String)无法覆盖 Person中的setName(java.lang.String),被覆盖的方法为final。
由此说明被final 修饰的方法是不能被重写的。
那么,final修饰的类是否可以被继承呢?
final class Person { private String name; public void setName(String name){ this.name = name; } } // 继承被final 修饰的Person类 public class Student extends Person{ }
运行结果
Error:(24, 30) java: 无法从最终Person进行继承。
由此说明被final 修饰的类是不能被继承的。
当没有出现异常时,异常处理语句中的finally 是否会被执行呢?
public class Student { public static void main(String[] args) { try { int i = 1; int result = i / 1; } catch (Exception e) { e.printStackTrace(); } finally { System.out.print(""没有出现异常时,执行finally""); } } }
运行结果
没有出现异常时,执行finally
当出现异常时,异常处理语句中的finally 是否会被执行呢?
public class Student { public static void main(String[] args) { try { int i = 1; int result = i / 0; } catch (Exception e) { e.printStackTrace(); } finally { System.out.print(""出现异常时,执行finally""); } } }
运行结果
java.lang.ArithmeticException: / by zero at Student.main(Student.java:27) 出现异常时,执行finally
由此可知,异常处理语句结构的一部分finally{},无论是否出现异常,finally{}一定会被执行。
最后我们再来看一下,finalize()方法是如何使用的?
class Person { private String name; public void setName(String name){ this.name = name; } public String getName(){ return name; } @Override protected void finalize() throws Throwable { System.out.print("调用finalize()方法,在Student对象从内存中删除之前对setName进行清理操作"); super.finalize(); } } public class Student extends Person { public static void main(String[] args) throws Throwable { Student s1 = new Student(); Student s2 = new Student(); System.out.println("s2=s1之前,s1指向的对象地址:"+s1); System.out.println("s2=s1之前,s2指向的对象地址:"+s2); // 设置name s1.setName("Rose"); s2.setName("Jack"); //将s1指向的对象地址赋给s2, 则s1和s2指向的是同一个对象地址 s2=s1; System.out.println("s2=s1之后,s1指向的对象地址:"+s1); System.out.println("s2=s1之后,s2指向的对象地址:"+s2); // 显式调用垃圾回收方法 触发finalize() System.gc(); System.out.println("学生名字:"+s1.getName()); } }
运行结果
s2=s1之前,s1指向的对象地址:Student@a09ee92 s2=s1之前,s2指向的对象地址:Student@30f39991 s2=s1之后,s1指向的对象地址:Student@a09ee92 s2=s1之后,s2指向的对象地址:Student@a09ee92 学生名字:Rose 调用finalize()方法,在Student对象从内存中删除之前对setName进行清理操作。 Process finished with exit code 0
从运行结果来看,在垃圾回收器执行的时候会调用被回收对象的finalize()方法。