java之final关键字的使用
文章内容选自尚硅谷,jdk8,eclipse环境
final关键字的使用
final关键字可以修饰类、方法、变量
final关键字修饰类
final关键字修饰的类不能够被继承,比如说java标准库中的String类、System类、StringBuffer类
package com.atguigu.java3;
public class FinalTest {
}
//class A extends String{
//
//}
注释的部分编译器会报错,这是因为标准库中的String类有关键字final修饰,表示String类不能够被继承
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
以上是标准库中的String定义,有关键字final修饰。
final修饰方法
final关键字修饰的方法表示改方法不能够被重写,比如说Object类中的getClass方法
//class AA{
// public void getClass(){
//
// }
//}
注释到的部分编译器也会报错,因为getClass方法返回当前对象所属类,在Object类中,该方法被final修饰,无法重写。
ps:按住crtl+shift+t找到Object类,再按住ctrl+o会显示该类的所有方法,点击getClass。
public final native Class<?> getClass();
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hash tables such as those provided by
可见,类中的getClass方法也有final修饰
ps:我们发现这儿的方法没有显示方法体,而且还有一个native关键字,native关键字的意思是该方法的方法体是由c或c++写的,不是用java代码写的,属于底层代码,故不显示。
final修饰变量
- final修饰的变量,此时的变量变为一个常量了,常量就意味着它不允许被修改。
- final修饰的变量,一般写作大写形式。
final修饰变量,则final也能修饰属性,因为属性也属于变量。final修饰属性的时候,可以显式赋值,也可以在代码块中初始化、构造器初始化。
final修饰属性时显式初始化
final修饰属性的时候不能够默认初始化
package com.atguigu.java3;
public class FinalTest {
final int WIDTH = 0;
}
如果没有final关键字,尽管如果不给属性WIDTH赋初值,采用默认初始化也为0,但是这儿有final关键字修饰,必须采用显式初始化。
ps:ctrl+shift+x能够把小写字母改为大写字母。
final修饰属性时代码块中初始化
package com.atguigu.java3;
public class FinalTest {
final int WIDTH = 0;
final int LEFT;
{
LEFT = 1;
}
}
final修饰属性时构造器中初始化
采用构造器初始化能够给对象的final属性赋自己需要的值,相较于显式赋值更加灵活。
package com.atguigu.java3;
public class FinalTest {
final int WIDTH = 0;
final int LEFT;
final int RIGHT;
{
LEFT = 1;
}
public FinalTest(){
RIGHT =2;
}
// public FinalTest(){
//
// }
}
注释掉的部分报错,通过构造器初始化的时候,注意必须在每个构造器内部都给final属性赋值,因为我们调用构造器的时候只能调用一个,因为得保证每个构造器都给final修饰的属性赋值。
如果在注释掉的构造器内部加上RIGHT的赋值语句,编译就通过了。
public class FinalTest {
final int WIDTH = 0;
final int LEFT;
final int RIGHT;
{
LEFT = 1;
}
public FinalTest(){
RIGHT =2;
}
public FinalTest(int n){
RIGHT = n;
}
}
此时可以通过构造器给属性RIGHT赋任意int型的值了。
ps:final修饰的属性不能够通过 对象.属性 来赋值,因为我们通过 对象.属性 来赋值,前提是现有了对象,而我们在创建对象的时候,所定义的属性必须有个初始值,这个初始值可以是默认初始值,也可以是构造器初始化的值,反正必须有一个值。可是我们在定义类的时候,把属性用final修饰了,属性就为一个常量了,又因为final修饰的属性不能用默认初始化。所以必须通过其他方式初始化后,才能创建对象。故 对象.属性 不能修改值,因为final属性是一个常量,不允许被修改。
final修饰局部变量
public class FinalTest {
final int WIDTH = 0;
final int LEFT;
final int RIGHT;
{
LEFT = 1;
}
public FinalTest(){
RIGHT =2;
}
public FinalTest(int n){
RIGHT = n;
}
public void show(final int num){
// num = 20;//常量不允许被修改,只能被调用
System.out.println(num);
}
public static void main(String[] args) {
FinalTest test = new FinalTest();
test.show(10);
}
}
输出结果为10
此处show方法之所以编译通过,是因为形参就只有被调用的时候才在栈空间中声明变量,并且传递一个实参值,有点类似于属性的显式初始化了。因此编译通过,由于已经用final修饰形参,故show方法内的num只能被调用,不能被修改。num = 20; 编译器会报错。
补充:static final修饰属性,意为全局常量,static关键字修饰的属性意味着通过类的加载而加载,就这一份,通过类直接调,体现全局,final体现常量。