继承的出现提高了代码的复用性,并方便开发。但是,有些类在描述完之后,不想被继承,或者有些类中的部分方法功能是固定的,不想让子类重写。这时就需要用到
final关键字
如同final的字面意思,最终的,不可变。
一、修饰变量
- final修饰局部变量,变量值不可改变。若重新赋值则报错“无法分配最终的局部变量。它必须为空且不能使用复合赋值”
final int i = 1;
i=2;//编译报错“The final local variable i cannot be assigned. It must be blank and not using a compound assignment”
- final修饰局部变量
需要手动赋值、不能二次赋值
final 数据类型 变量名 = 值
public class Student {
final String name = "你好";
public Student() {
}
public String getName() {
return name;
}
public Student(String name) { //有参构造属于二次赋值,会报错
this.name = name;
}
public void setName(String name) { //set方法属于二次赋值,会报错
this.name = name;
}
}
- 当修饰引用数据类型变量,变量的引用不可以被改变,但是变量本身指向的对象或者数组的值可以改变
public static void main(String[] args) {
final A t = new A("Hello");
System.out.println(t.get());
t.set("World");//重新set一个值
System.out.println(t.get());//打印结果变成了“World”,说明变量本身指向的对象的值可以改变
}
class A{
private String str;
public A(String str) {
this.str = str;
}
public String get() {
return str;
}
public void set(String a) {
this.str = a;
}
}
- final修饰的常量,可以不在声明的同时进行赋值操作,而是在构造代码块中或者在构造方法中对其进行赋值操作
class A{
final int i;
public A(int i) {//构造方法
this.i = i;
}
}
二、修饰方法、该方法不可被子类重写。但是可以被多次重载!
如果在父类中使用final 来修饰方法,那么该方法就被定义为private,即不可重写,即方法被私有化了。
不能被重写
public class Test {
public static void main(String[] args) {
Universe a = new Universe();
a.hello();//此时编译报错Cannot override the final method from World
}
}
class World{
public final void hello() {
System.out.println("Hello");
}
}
class Universe extends World{
public void hello() {
System.out.println("nihao");
}
}
能被重载
编译通过,运行结果为HelloWorld
public class Test1 {
public static void main(String[] args) {
World a = new World();
a.hello("");
}
}
class World{
public final void hello() {
System.out.println("Hello");
}
public final void hello(String a) {
System.out.println("HelloWorld");
}
}
三、修饰类
final修饰的类不能有子类,不能被继承,比如:Math,String,但是可以继承其他类。
下列代码编译通过
final class Hello extends World{}
class World{}
四、修饰对象
被final修饰的对象,地址值不能改变,但是对象中的属性值可以改变,可以跟上面介绍的修饰引用数据类型变量比较理解
final 数据类型 对象名 = new 对象();
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class Test {
public static void main(String[] args) {
final Person p1 = new Person("haha",26);
//p1 = new Person("nihao",18); 新new的对象相当于给地址值二次赋值了,会报错,
p1.setName("你好"); //但是对象中的属性值可以改变
p1.setAge(66);
}
}