一、final关键字的基本用法
1)修饰类:当用final修饰一个类时,表明这个类不能被继承,同时,final类中所有成员方法都会被隐式的指定为final方法。
2)修饰方法:将方法锁定,以防止任何继承类修改它的含义。
备注:父类中,用final声明的方法是不能被子类覆盖的,但是同时用private修饰符的话,就可以,因为父类中的方法用private修饰时,对子类是不可见的,也就是说子类没有继承父类private修饰的方法,自然子类可以自己声明相应的方法。(但这就不是严格意义上父子类函数覆盖了)
3)修饰变量:对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后不能再让其指向另一个对象。(换句话说:final修饰的变量内容是不能修改的,如果final修饰一个对象的引用,那么指的是这个对象的地址值是无法改变的,也就是不能再指向另一个对象,但是对象的内容还是可以修改的)
二、final变量和普通变量的区别
举个例子:
public class Test {
public static void main(String[] args) {
String a = "hello2";
final String b = "hello";
String d = "hello";
String c = b + 2;
String e = d + 2;
System.out.println((a == c));
System.out.println((a == e));
}
}#输出的第一个比较结果为true,第二个为false。
解释:当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用,也就是说在用到该final变量的地方,相当于访问这个常量,不需要在运行时确定。这种跟C语言中的宏替换有点像。因此在上面一段代码中,变量b被final修饰,因此会被当做编译期常量,所以在使用到b的地方会直接将变量b替换成它的值。而对于变量d的访问却需要在运行时通过链接来进行,两者在获取值的阶段不同,导致程序运行过程中的不一样。(编译过程可以细分为4个阶段:预处理pre-processing/编译compiling/汇编assembling/链接linking;这个会在往后的随笔中进行阐述)
三、final和static的用法区别
final:
1)final作用于变量是用来保证变量不可变,而static作用于成员变量用来表示只保存一份副本。
2)final不能用于修饰构造方法
3)final类不能被继承,没有子类,final类中的方法默认是final的。
4)final方法不能被子类的方法重写,可以被重载。【重载是指一个类中可以有同样的修饰符,返回值,方法名,但参数个数或顺序不同的方法。而重写指的是子类继承父类后,重写父类的方法。重写是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变。即外壳不变,核心重写!】
5)父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。【区分一下同时写private和final的说法】
6)final类的方法能否被同一个包的类访问取决于访问控制符,与final无关。
7)使用final关键字定义变量,不一定说一定要在变量定义的同时给定变量的具体数值,也可以在构造方法中完成初始化。
8)在使用final关键字定义的方法里不一定要使用final关键字定义里面的变量。
static:
1)被static修饰的成员变量和成员方法独立于该类的任何对象。
2)static变量前可以有private修饰,表示这个变量可以在类的静态代码块中,或者类的其他静态成员方法中使用。
3)static不能修饰局部变量。
4)static final和final static没什么区别,一般static写在前面。
5)static修饰的属性强调它们只有一个,final修饰的属性表明是一个常数(创建后不能被修改);java中没有全局变量的概念,static变量在第一次使用的时候初始化,但只会有一份成员对象(也就是还可以改变)。【static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问。】
6)static关键字表明一个成员变量或者成员方法可以在没有所属的类的实例变量的情况下被访问。