侧边栏壁纸
  • 累计撰写 44 篇文章
  • 累计创建 8 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Java final修饰符理解

博主
2024-01-22 / 0 评论 / 1 点赞 / 8 阅读 / 6379 字 / 正在检测是否收录...

final在Java中是最终的意思,也就是完结器,表示不可再变,final 应用于类、方法和变量时意义是不同的,但本质是一样的,都表示不可改变

使用 final 关键字声明类、变量和方法需要注意以下几点:

  • final 用在变量的前面表示变量的值不可以改变,此时该变量可以被称为常量。

  • final 用在方法的前面表示方法不可以被重写(子类中如果创建了一个与父类中相同名称、相同返回值类型、相同参数列表的方法,只是方法体中的实现不同,以实现不同于父类的功能,这种方式被称为方法重写,又称为方法覆盖。这里了解即可,教程后面我们会详细讲解)。

  • final 用在类的前面表示该类不能有子类,即该类不可以被继承。

final 修饰变量

final 修饰的变量即成为常量,只能赋值一次,但是 final 所修饰局部变量成员变量有所不同。

  1. final 修饰的局部变量必须使用之前被赋值一次才能使用。

  2. final 修饰的成员变量在声明时没有赋值的叫“空白 final 变量”。空白 final 变量必须在构造方法或静态代码块中初始化。

注意:final 修饰的变量不能被赋值这种说法是错误的,严格的说法是,final 修饰的变量不可被改变,一旦获得了初始值,该 final 变量的值就不能被重新赋值。

public class FinalDemo {
    static void demo(){
        //定义方法变量
        final int a;
        //只能赋值一次
        a = 100;
        //a = 200; //第二次赋值会报错
        System.out.println(a);
        //或者定义的时候赋值都行
        final int b = 200;
        System.out.println(b);
    }
​
    // 实例常量
    final int a = 5; // 直接赋值
    final int b; // 空白final变量
​
    // 静态常量
    final static int c = 12;// 直接赋值
    final static int d; // 空白final变量
    // 静态代码块
    static {
        // 初始化静态变量
        d = 32;
    }
​
    // 构造方法
    finalDemo() {
        // 初始化实例变量
        b = 3;
        // 第二次赋值,会发生编译错误
        // b = 4;
    }
    public static void main(String[] args) {
        demo();
​
    }
}

上述代码第7行再次赋值会报错,因为final只允许赋值一次,表示最终结果,不能再次被赋值,第32行也是如此。无论是那种常量只能赋值一次,再次赋值会编译报错

final修饰方法

final 修饰的方法不可被重写,如果出于某些原因,不希望子类重写父类的某个方法,则可以使用 final 修饰该方法。

Java 提供的 Object 类里就有一个 final 方法 getClass(),因为 Java 不希望任何类重写这个方法,所以使用 final 把这个方法密封起来。但对于该类提供的 toString() 和 equals() 方法,都允许子类重写,因此没有使用 final 修饰它们。

下面程序试图重写 final 方法,将会引发编译错误。

public class FinalMethodDemo {
    public final void finalTest(){
    }
}
​
class Test extends FinalMethodDemo{
    public void finalTest(){
        
    }
}

image-20220523163548052

上述代码中,父类 FinalMethodDemo 定一个了一个方法 finalTest ,子类 Test 继承了父类,并尝试重写 finalTest 方法 ,但是因为是final类型,不能被重写,所以会编译报错。

对于一个 private 方法,因为它在当前类中可见,其子类无法访问该方法,所以子类无法重写该方法——如果子类中定义一个与父类 private 方法有相同方法名、相同形参列表、相同返回值类型的方法,也不是方法重写,只是重新定义了一个新方法。因此,即使使用 final 修饰一个 private 访问权限的方法,依然可以在其子类中定义与该方法具有相同方法名、相同形参列表、相同返回值类型的方法。

下面程序示范了如何在子类中“重写”父类的 private final 方法。

public class FinalMethodDemo {
    private final void finalTest(){
    }
}
​
class Test extends FinalMethodDemo{
    //不会报错,因为这个方法和父类完全不是同一个方法
    public void finalTest(){
​
    }
}

上述的例子木有问题,因为父类中的方法为 private 类型,在当前类中可见,与子类没有关联,所以子类“重写”完全一模一样的方法也是木有问题的。

final 修饰的方法仅仅是不能被重写,并不是不能被重载,因此下面程序完全没有问题。

public class FinalMethodDemo {
    //final只是不能被重写,但完全可以重载
    public final void finalTest(){}
    public final void finalTest(String arg){}
}

final修饰类

final 修饰的类不能被继承。当子类继承父类时,将可以访问到父类内部数据,并可通过重写父类方法来改变父类方法的实现细节,这可能导致一些不安全的因素。为了保证某个类不可被继承,则可以使用 final 修饰这个类。

下面代码示范了 final 修饰的类不可被继承。

public final class FinalClassDemo {}
​
//会编译报错,无法继承从final继承
class Test extends FinalClassDemo{}

image-20220523164836407

因为 FinalClassDemo 类是一个final类,Test 类试图继承,这会导致编译错误。

final 修饰符使用总结

1. final 修饰类中的变量

表示该变量一旦被初始化便不可改变,这里不可改变的意思对基本类型变量来说是其值不可变,而对对象引用类型变量来说其引用不可再变。其初始化可以在两个地方:一是其定义处,也就是说在 final 变量定义时直接给其赋值;二是在构造方法中。这两个地方只能选其一,要么在定义时给值,要么在构造方法中给值,不能同时既在定义时赋值,又在构造方法中赋予另外的值。

2. final 修饰类中的方法

说明这种方法提供的功能已经满足当前要求,不需要进行扩展,并且也不允许任何从此类继承的类来重写这种方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。在声明类中,一个 final 方法只被实现一次。

3. final 修饰类

表示该类是无法被任何其他类继承的,意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。

对于 final 类中的成员,可以定义其为 final,也可以不是 final。而对于方法,由于所属类为 final 的关系,自然也就成了 final 型。也可以明确地给 final 类中的方法加上一个 final,这显然没有意义。


1
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
  3. QQ打赏

    qrcode qq

评论区