final修饰符一直是Java基础知识中非常重要的考点,final关键字可以用来修饰类、变量、方法。final变量不能重新赋值,子类不能覆盖父类的final方法,final类不能有子类。这些都是非常基础的考点,但是也是非常重要的内容,不容忽视。
1.final修饰成员变量
(1)final修饰的成员变量一旦赋值后,不能被重新赋值。
(2)final修饰的实例Field,要么在定义该Field的时候指定初始值,要么在普通初始化块或构造器中指定初始值。但是如果在普通初始化块中为某个实例Field指定了初始值,则不能再在构造器中指定初始值。
(3)final修饰的类Field,要么在定义该Field的时候指定初始值,要么在静态代码块中定义初始值。
(4)如果在构造器或初始化块中对final成员变量进行初始化,则不要在初始化之前就访问该成员的值。
package cn.lsl;
public class FinalTest {
final int a = 5; //直接赋值
final String str; //普通代码块中赋值
{
str = "zhangsan";
}
final int b; //构造器中赋值
public FinalTest(){
b = 7;
}
final static int c = 8; //直接赋值
final static int d; //静态代码块中赋值
static{
d = 9;
}
//如果在构造器或初始化块中对final成员变量进行初始化,则不要在初始化之前就访问该成员的值。
final int age;
{
//System.out.println(age);
age = 22;
System.out.println(22);
}
}
2.final修饰局部变量
(1)系统不会对局部变量进行初始化,布局变量必须要显示的初始化。所以使用final修饰的局部变量,既可以在定义的时候指定默认值,也可以不指定默认值。
(2)final修饰形参的时候,不能为该形参赋值。
3.final修饰基本数据类型变量和修饰引用类型变量的区别
使用final修饰基本类型的变量,一旦对该变量赋值之后,就不能重新赋值了。但是对于引用类型变量,他保存的只是引用,final只能保证引用类型变量所引用的地址不改变,但不保证这个对象不改变,这个对象完全可以发生改变。
final修饰的引用类型变量不能被重新赋值,但是可以改变引用变量所引用对象的内容。
4.final的“宏变量”
(1)final修饰符的一个重要用途就是“宏变量”。当定义final变量时就该为该变量指定了初始值,而且该初始值可以在编译时就确定下来,那么这个final变量本质上就是一个“宏变量”,编译器会把程序中
所有用到该变量的地方直接替换成该变量的值。
package cn.lsl;
public class FinalTest {
public static void main(String[] args){
final String name = "小明" + 22.0;
final String name1 = "小明" + String.valueOf(22.0);
System.out.println(name == "小明22.0");
System.out.println(name1 == "小明22.0");
}
}
final String name1 = "小明" + String.valueOf(22.0);中调用了String类的方法,因此编译器无法再编译的时候确定name1的值,所以name1不会被当成“宏变量”。
5.final修饰方法
用final修饰的方法不能被重写。用final修饰的类不能有子类。
因为重写的前提是子类可以从父类中继承此方法,如果父类中final修饰的方法同时访问控制权限为private,
将会导致子类中不能直接继承到此方法,因此,此时可以在子类中定义相同的方法名和参数,此时不再产生重写与final的矛盾,而是
在子类中重新定义了新的方法。
6.不可变类
不可变类是指创建该类的实例后,该实例的Field是不可改变的。
如果创建自定义的不可变类,应该遵循如下规则
(1)使用private和final修饰符来修饰该类的Field。
(2)提供带参数的构造器,用于传入参数来初始化类里的Field。
(3)仅为该类的Field提供getter方法,不要为该类的Field提供setter方法。
(4)如果有必要,重写Object类的hashCode和equals方法。
package cn.lsl;
public class Address {
private final String detail;
private final String postCode;
public Address() {
this.detail = "";
this.postCode = "";
}
public Address(String detail, String postCode) {
this.detail = detail;
this.postCode = postCode;
}
public String getDetail() {
return detail;
}
public String getPostCode() {
return postCode;
}
public boolean equals(Object obj){
if(this == obj){
return true;
}
if(obj !=null && obj.getClass() == Address.class){
Address ad = (Address)obj;
if(this.getDetail().equals(ad.getDetail()) && this.getPostCode().equals(ad.getPostCode())){
return true;
}
}
return false;
}
public int hashCode(){
return detail.hashCode() + postCode.hashCode() * 31;
}
}
因为final修饰引用类型变量时,表示这个引用变量不可重新被赋值,但引用类型变量所指向的对象依然可被改变。所以在创建不可变类的时候,如果包含的Field类型是可变的,那么这个不可变类就创建失败了。
Final修饰符作为Java基础中的重点内容,延伸出来的知识和考点还有很多,本文也只是总结了一部分比较重要的内容,想要全方位学习final修饰符的后续知识,可以观看本站的Java基础教程,快速熟练掌握final修饰符的全部用法。
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习