Final与Static关键字的理解

641 阅读5分钟

在开发中会经常遇到Final与Static修饰变量、方法、类,在代码review的时候大佬也一直强调不要出现魔法值,例如变量的赋值、实参的传入等等,在声明变量、方法、类的时候也应当考虑使用周期,增加代码的可读性与服务器的性能,为此总结下Final与Static在修饰的时候是什么含义,同时后文将描述在Java内存区域,每一块区域存放着什么数据,一个类的实例产生将会经过哪些步骤等等;

Final关键字的理解

在Java中,final可以修饰变量、方法、参数、类,在不同的场景下有细微的区别,但是总体含义上可以理解为“不可变”;

public class FinalCode {

    int value;

    /**
     * 修饰成员变量  声明时赋值
     */
    final int finalIntOne = 1;
    
    /**
     *  修饰成员变量 通过构造函数赋值
     */
    final int finalIntTwo;

    public FinalCode(int finalIntTwo) {
        this.finalIntTwo = 2;
    }

    public FinalCode(final int value, final int finalIntTwo) {

        // value = 5;   不能修改形参数值  
        this.value = value;
        this.finalIntTwo = finalIntTwo;
    }

    public static void main(String[] args) {

        //修饰局部变量   初始化之后不能改变其值
        final int finalValue = 1;
        //value1 = 4;   //cannot assign a value to final  variable 'finalValue'

        //先声明再赋值
        final int value;
        value = 4;

        // final修饰引用变量时,则在对其初始化之后便不能再让其指向另一个对象,但是引用的对象的值是可以改变的
       final FinalCode finalCode = new FinalCode(1);
        //cannot assign a value to final  variable 'finalCode'  去掉final是可以的将对象指向FinalCode(2)
        //finalCode = new FinalCode(2);   
        finalCode.value = 3;
    }
}

1、修饰局部变量 (Ep:mani方法)

a : 首先看看main方法中用final修饰局部变量finalValue,在初始化之后不能改变其值;

b : 可以先声明再赋值;

c : final修饰引用变量时,则在对其初始化之后便不能再让其指向另一个对象,但是引用的对象的值是可以改变的;

可以理解为随着main方法进栈,用final修饰的局部变量称为不可能变变量存在于栈中(final修饰的成员变量属于常量,常量在类编译时期载入类的常量池中),在堆中对象的地址值是不可以改变的,但是指向对象的内容是可以改变的。

2、修饰成员变量 (Ep:FinalCode类)

a : 在使用之前必须确保已经赋值;

b : 有且只有二个地方可以赋值(声明时、构造函数);

3、修饰方法

用final关键字修饰方法,它表示该方法不能被覆盖。

4、修饰类

使用final关键字修饰的类是无法被继承的,例如String、System等等;

总结:

1、修饰局部变量,该变量只能被赋值一次且它的值无法被改变,修饰引用对象时,对象地址值不能变,值可以改变。
2、修饰成员变量,我们必须在声明时或者构造方法中对它赋值;
3、用来修饰方法参数,表示在变量的生存期中它的值不能被改变;
4、修饰方法,表示该方法无法被重写;
5、修饰类,表示该类无法被继承。

Static 关键字的理解

1、修饰成员变量和成员方法:

static 修饰的成员变量属于类,不属于单个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用;
被static 声明的成员变量属于静态成员变量,静态变量存放在 Java 内存区域的方法区;

2、静态代码块:

静态代码块定义在类中方法外,静态代码块在非静态代码块之前执行
(静态代码块—>非静态代码块—>构造方法)该类不管创建多少对象,静态代码块只执行一次;

3、静态内部类(static修饰类的话只能修饰内部类):

静态内部类与非静态内部类之间存在一个最大的区别:非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围类,但是静态内部类却没有,没有这个引用就意味着:
    它的创建是不需要依赖外围类的创建。
    它不能使用任何外围类的非static成员变量和方法。

4、静态代码块与非静态代码块的区别

  相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个,定义多个时按定义的顺序执行;
  不同点:静态代码块只在第一次产生对象的时候执行,而非静态代码块在产生一次对象就执行一次;

5、非静态代码块与构造函数的区别:

    非静态代码块是给所有对象进行统一初始化;
    构造函数是给对应的对象初始化,因为构造函数是可以多个的,运行哪个构造函数就会建立什么样的对象,但无论建立哪个对象,都会先执行相同的构造代码块。构造代码函数中定义的是不同对象共性的初始化内容。

鄙人不才,在您面前献丑只愿与您结伴而行,文章若有不当之处,望大佬指点一二;如果我对您有帮助的话,还希望您能点赞分享,成长是一场苦涩的独自修行,我很需要您的陪伴与支持,这也是鄙人不断前行的根本动力,让我们在互相陪伴见证彼此生长的同时能够感染身边最亲近的人一同成长,鄙人在此叩谢!