final
修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载
/*
* 当你在类中定义变量时,在其前面加上final关键字,那便是说,
* 这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,
* 而对于对象变量来说其引用不可再变。其初始化可以在两个地方,一是其定义处,
* 二是在构造函数中,两者只能选其一
*/
public class FinalDemo{
final int i ;
final int k = 3 ;
public FinalDemo(){
i = 1;
}
public FinalDemo(int j){
i = j;
//k = 4; //无法再为k赋值
}
public static void main(String[] args) {
//System.out.println("Hello Landor!");
FinalDemo fd1 = new FinalDemo();
FinalDemo fd2 = new FinalDemo(2);
System.out.println(fd1.i); // fd1.i=1
System.out.println(fd2.i); // fd2.i=2
System.out.println(fd2.k); // fd2.k=3
System.out.println(fd2.k); // fd2.k=3
//fd1.i++; //无法再为i赋值
}
}
/*
* 用final修饰方法中的参数时,也分两种情况:
* 第一种:修饰基本数据类型,此时若用final来修饰,则在方法中只能引用
* 该变量,并不能修改该变量,其实这个时候纯属多此一举,基本数据类型传递
* 本来就是值传递,不管你在方法中是否改动该变量,该变量的值都不会变
* 第二种:修饰引用类型,此时若用final修饰,并不是说不能在方法中修改该
* 对象,只是说不能修改该对象的引用地址!比如在方法public static void p(final Person per)
* 中,依然可以用per.setName("Sugite");来修改name字段,但是不能用per = new Person("Baka");
* 来重新为per分配一个地址空间。
* 注:方法中的内部类在用到方法中的参数变量时,此参数变量也必须声明为final才可使用
*/
class Person{
private String name;
Person(String n){
this.name = n ;
}
public String getName(){
return this.name;
}
public void setName(String n){
this.name = n;
}
}
public class FinalDemo{
void print(final String str){
class InnerTest{
InnerTest(){
System.out.println(str);
}
}
InnerTest it=new InnerTest ();
}
public static void main(String[] args){
/-------------------------------------/
int i = 2;
System.out.println(i);
modify(i);
System.out.println(i);
/-------------------------------------/
Person per = new Person("Landor");
FinalDemo test=new FinalDemo();
test.print("Hello Landor!!!");
/-------------------------------------/
p(per);
System.out.println(per.getName());
}
public static void p(final Person per ){
per.setName("Sugite"); //可以修改per中的字段
//per = new Person("Baka");//不能重新分配
System.out.println(per.getName());
}
public static void modify(final int j){
//j = 3; //不行,编译会出错
System.out.println(j);
}
}
/*
* 用final修饰方法时,一般有两个作用
* 第一:如果你写的一个类中的方法已经很完善,你不希望它的子类override该方法
* 则可以在方法前加上final;
* 第二:使用final修饰的方法在编译的时候不会产生“invoke”,而是直接嵌入到“inline”
* 中进行编译,类似于“整体化”的代码,效率比较高,但是如果此类方法用得比较多,那么
* 主体代码将过于庞大,将会影响效率。
*/
class A{
public final void p(){
System.out.println("Hello Landor");
}
}
class B extends A{
public void p(){//编译将会出错,提示此时无法override方法p()
System.out.println("Hello Sugite");
}
}
public class FinalDemo{
public static void main(String args[]){
A c = new B();
c.p();
}
}
/*
* 用final修饰类时,只有一个目的:就是不允许任何类继承此类
* 所以final类即叶子类或者太监类,没有子孙
* 其他地方和普通类没有任何不同
* 例子略!
*/
finally
异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)。一般异常处理块需要。
/*
* finally只有在try catch的时候才会出现,表示总是执行。
* 一般用于close,比如I/O流的关闭,或者database的关闭等。
* 但是上次在网上看到一个有趣的东西:
* try{
* System.out.println("a");
* return ;
* }catch(Exception e){
* e.printStackTrace();
* }finally{
* System.out.println("b");
* }
* 这个时候finally还能否执行呢?
*/
public class FinallyDemo{
public static void main(String[] args) {
//System.out.println("Hello Landor!");
try{
System.out.println("a");
//System.exit(1) ;
return ;
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("b");
}
}
}
/*
运行结果:
a
b
那么到底是return先执行还是finally先执行呢,有兴趣可以去网上查一下,我记不太清
好像是return先将返回值存储,再执行finally,最后执行return;
*/
finalize
方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。
Java中所有类都从Object类中继承finalize()方法。
当垃圾回收器(garbage colector)决定回收某对象时,就会运行该对象的finalize()方法。值得C++程序员注意的是,finalize()方法并不能等同与析构函数。Java中是没有析构函数的。C++的析构函数是在对象消亡时运行的。由于C++没有垃圾回收,对象空间手动回收,所以一旦对象用不到时,程序员就应当把它delete()掉。所以析构函数中经常做一些文件保存之类的收尾工作。但是在Java中很不幸,如果内存总是充足的,那么垃圾回收可能永远不会进行,也就是说filalize()可能永远不被执行,显然指望它做收尾工作是靠不住的。
那么finalize()究竟是做什么的呢?它最主要的用途是回收特殊渠道申请的内存。Java程序有垃圾回收器,所以一般情况下内存问题不用程序员操心。但有一种JNI(Java Native Interface)调用non-Java程序(C或C++),finalize()的工作就是回收这部分的内存。
|