关于 final 关键字 && 类的初始化顺序


 

1、final 关键字

1.1、final 修饰变量和对象

  • 当用 final 修饰对象,对于基本类型,final 使数值恒定不变

  • 对于对象引用,final 使引用恒定不变。一旦引用被初始化指向了某个对象,它就不能改为指向其他对象。 但是,对象本身是可以修改的,Java 没有提供将任意对象设为常量的方法。

  • 在参数列表中,将参数声明为 final ,意味着:在方法中不能改变参数指向的对象或基本变量
     
    示例:

package com.ttt.gof;

import com.alibaba.fastjson.JSON;
import com.qiuwan.gof.entity.User;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TestFinal {
    
    

    public static void main(String[] args) {
    
    

        User user = new User();
        user.setUserId(123);
        user.setUserName("张三");
        final User finalUser = user;
        log.info("finalUser = {}", JSON.toJSONString(finalUser));
        user.setUserName("李四");
        log.info("user = {}", JSON.toJSONString(user));
        log.info("finalUser = {}", JSON.toJSONString(finalUser));
        finalUser.setUserName("王五");
        log.info("finalUser = {}", JSON.toJSONString(finalUser));

        // finalUser = new User(); // 这种写法报异常 Exception: Cannot assign a value to final variable 'finalUser'
        // finalUser = user;  // 这种写法报异常 Exception: Cannot assign a value to final variable 'finalUser'

        /*********************************/
        System.out.println();
        /*********************************/
        Long rLong = 10L;
        final Long mLong = rLong;
        log.info("mLong = {}", mLong);
        rLong = 20L;
        log.info("rLong = {}", rLong);
        log.info("mLong = {}", mLong);
        // mLong = 20L;    // 这种写法报异常 Exception: Cannot assign a value to final variable 'mLong'
        // mLong = rLong;  // 这种写法报异常 Exception: Cannot assign a value to final variable 'mLong'

        /*********************************/
        System.out.println();
        /*********************************/
        String str = "张三";
        final String fStr = str ;
        final String f_Str = "王五";
        log.info("fStr = {}", fStr);
        log.info("f_Str = {}", f_Str);
        str = "李四";
        // fStr = str;      // 这种写法报异常 Exception: Cannot assign a value to final variable 'fStr'
        // f_Str = str;     // 这种写法报异常 Exception: Cannot assign a value to final variable 'f_Str'
        // fStr = "马六";   // 这种写法报异常 Exception: Cannot assign a value to final variable 'fStr'
        // f_Str = "马六";  // 这种写法报异常 Exception: Cannot assign a value to final variable 'f_Str'
        log.info("fStr = {}", fStr);
        log.info("f_Str = {}", f_Str);

    }

}

 
打印结果:
 

15:02:51.529 [main] INFO com.ttt.gof.TestFinal - finalUser = {
    
    "userId":123,"userName":"张三"}
15:02:51.538 [main] INFO com.ttt.gof.TestFinal - user = {
    
    "userId":123,"userName":"李四"}
15:02:51.538 [main] INFO com.ttt.gof.TestFinal - finalUser = {
    
    "userId":123,"userName":"李四"}
15:02:51.538 [main] INFO com.ttt.gof.TestFinal - finalUser = {
    
    "userId":123,"userName":"王五"}

15:02:51.539 [main] INFO com.ttt.gof.TestFinal - mLong = 10
15:02:51.539 [main] INFO com.ttt.gof.TestFinal - rLong = 20
15:02:51.539 [main] INFO com.ttt.gof.TestFinal - mLong = 10

15:02:51.543 [main] INFO com.ttt.gof.TestFinal - fStr = 张三
15:02:51.543 [main] INFO com.ttt.gof.TestFinal - f_Str = 王五
15:02:51.543 [main] INFO com.ttt.gof.TestFinal - fStr = 张三
15:02:51.543 [main] INFO com.ttt.gof.TestFinal - f_Str = 王五

Process finished with exit code 0

1.2、final 修饰的方法

  • final 修饰的方法,其子类无法通过覆写而改变方法的行为。这是出于继承的考虑,确保方法的行为不会因为继承而改变。只有在为了明确禁止覆写方法时,才使用 final.

  • 类中所有的 private 方法都隐式的指定为 final。因为不能访问 private 方法,所以不能覆写它。可以给 private 方法添加 final 修饰,但是并不能给方法带来额外的含义。


 

1.3、final 类

  • 当一个类是 final (final 关键字在类定义之前),就意味着它不能被继承。之所以这么做,是因为类的设计就是永远不需要改动,或者是出于安全考虑不希望它有子类。

  • final 类的属性可以根据个人选择是或不是 final。这同样适用于不管类是否是 final 的内部 final 属性。然而,由于 final 类禁止继承,类中所有的方法都被隐式地指定为 final,所以没有办法覆写它们你可以在 final 类中的方法加上 final 修饰符,但不会增加任何意义。
     

2、类的初始化顺序

 
静态成员 >> 静态代码块(多个静态代码块时,按代码顺序) >> 普通成员 >> 非静态代码块 >> 构造函数
 
 
在这里插入图片描述
 
示例:
 

package com.ttt.gof;


public class Insect {
    
    


    private int i = 10;

    protected int j;

    // 父类构造函数
    Insect() {
    
    
        System.out.println("i = " + i + ", j = " + j);
        j = 40;
    }

    // 静态变量
    private static int x1 = printInit("static Insect.x1 init");

    static int printInit(String s) {
    
    
        System.out.println(s);
        return 58;
    }

    // 父类代码块
    {
    
    
        System.out.println("Insect ordinary coding chunk");
    }

   static {
    
    
       System.out.println("Insect static coding chunk");
    }

}

package com.ttt.gof;

public class Beetle extends Insect {
    
    

    private int k = printInit("Beetle.k.initialized");

    // 子类构造函数,最后执行
    public Beetle() {
    
    
        System.out.println("k = " + k);
        System.out.println("j = " + j);
    }

    // 子类静态变量
    private static int x2 = printInit("static Beetle.x2 init");

    // 子类代码块
    {
    
    
        System.out.println("Beetle ordinary coding chunk");
    }

    public static void main(String[] args) {
    
    
        System.out.println("Beetle constructor");
        Beetle beetle = new Beetle();
    }

}

 
控制台打印结果:

在这里插入图片描述

static Insect.x1 init
Insect static coding chunk
static Beetle.x2 init
Beetle constructor
Insect ordinary coding chunk
i = 10, j = 0
Beetle.k.initialized
Beetle ordinary coding chunk
k = 58
j = 40

 
 
 
 
 
 
 
 
 
.

猜你喜欢

转载自blog.csdn.net/weixin_41922349/article/details/110129376
今日推荐