java理论七:关键字static、final理解

参考致谢:
[static关键字解析-例子] https://www.cnblogs.com/dolphin0520/p/3799052.html
[static补充] https://www.cnblogs.com/dolphin0520/p/10651845.html
[static\final区别] https://blog.csdn.net/qq1623267754/article/details/36190715
[final内存语义-重排序] https://blog.csdn.net/weixin_42546729/article/details/113867060?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.base

【final深入文章】https://juejin.im/entry/58c4811161ff4b005d94fed2#comment

1 static关键字解析

1.1 static的用途

1、static方法–静态方法

静态方法是为了方便在不创建对象的情况下调用。比如jdk的Collections类中的一些方法、单例模式的getInstance方法、工厂模式的create/build方法、util工具类中的方法。

(1) 对于静态方法是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了

(2) 在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。

2、static变量–静态变量

把一个变量声明为静态变量通常基于以下三个目的:

  • 作为共享变量使用
  • 减少对象的创建
  • 保留唯一副本—单例模式

3、static 代码块

静态代码块通常来说是为了对静态变量进行一些初始化操作,比如单例模式、定义枚举类:

为什么说static块可以用来优化程序性能?
因为它的特性:只会在类加载的时候执行一次
—>因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

4、静态内部类

使用static来修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象。称为静态内部类(也可称为类内部类)。

  • 除了写在一个类的内部以外,static内部类具备所有外部类的特性(内部类中的顶级类)。
  • static内部类,不能访问外部类的实例成员,只能访问外部类的类成员。

静态内部类和非静态内部类区别:
非静态内部类对象持有外部类对象的引用,而静态内部类对象不会持有外部类对象的引用;

注意:

1.非静态内部类中不允许定义静态成员;
2.外部类的静态成员不可以直接使用非静态内部类;

5、静态导入

静态导入其实就是import static,用来导入某个类或者某个包中的静态方法或者静态变量。

注意:static和“this、super”势不两立,static跟具体对象无关,而this、super正好跟具体对象有关。

1.2 static关键字的误区

1.static关键字会改变类中成员的访问权限吗?否

Java中的static关键字不会影响到变量或者方法的作用域。在Java中能够影响到访问权限的只有private、public、protected(包括包访问权限)这几个关键字。

2.能通过this访问静态成员变量吗?可以

静态成员变量虽然独立于对象,但可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。

3.static能作用于局部变量么?不可以

在Java中切记:static是不允许用来修饰局部变量。这是Java语法的规定。

常见的笔试面试题—static执行顺序

public class Test extends Base{
    //2.加载发现继承Base类  4.加载Test,执行静态代码块
    static{
        System.out.println("test static");
    }     
    //7.Test构造方法执行
    public Test(){
        System.out.println("test constructor");
    }     
    //1.执行开始找main,加载Test类 
    //5.都加载完之后,main方法执行new Test()的时候会先调用父类的构造器Base
    public static void main(String[] args) {
        new Test();
    }
}
class Base{ 
   //3.Base类加载,执行静态代码块 
   static{
        System.out.println("base static");
    } 
    //6.Base构造方法执行  
    public Base(){
        System.out.println("base constructor");
    }
}
//提问:输出结果
base static
test static
base constructor
test constructor

1.3 static变量和普通成员变量区别

  • 所属不同。static变量属于类,不单属于任何对象;普通成员变量属于某个对象
  • 存储区域不同。static变量位于方法区;普通成员变量位于堆区。
  • 生命周期不同。static变量生命周期与类的生命周期相同;普通成员变量和其所属的对象的生命周期相同。
  • 不可对象序列化。在对象序列化时(Serializable),static变量会被排除在外(因为static变量是属于类的,不属于对象)

1.4 类的构造器到底是不是static方法?【深挖】

关于类的构造器是否是static方法有很多争议,在《java编程思想》一书中提到“类的构造器虽然没有用static修饰,但是实际上是static方法”,个人认为这种说法有点欠妥,原因如下:

1)是否与对象关联

  • 构造器负责在创建一个实例对象的时候,对实例进行初始化操作,实际上构造器有一个隐藏的参数this引用,this是跟已经创建的对象绑定的。(即jvm在堆上为实例对象分配了相应的存储空间后,需要调用构造器对实例对象的成员变量进行初始化赋值操作)
  • static方法,由于static不依赖于任何对象就可以进行访问,也就是说和this是没有任何关联的。
    故从有没有this引用去讲,类的构造器不是static方法。

2)JVM指令不同

  • 类的构造器时实执行的是invokespecial指令,他是用来调用实例方法,用来特殊调用父类方法、private方法和类的构造器。
  • static方法是调用的是invokestatic指令,就是用来调用执行static方法。
    在这里插入图片描述

2 final

final表示不可改变,可以修饰:属性,方法,类,局部变量(方法中的变量)

2.1 final的使用

1、final修饰的属性

  • final修饰的属性的初始化可以在编译期,也可以在运行期,初始化后不能被改变。
  • final修饰的属性跟具体对象有关,在运行期初始化的final属性,不同对象可以有不同的值。
  • final修饰的属性表明是一个常数(创建后不能被修改)。

2、 final修饰的方法

表示该方法在子类中不能被重写,

3、final修饰的

表示该类不能被继承。

4、final修饰的基本类型数据

-final会将值变为一个常数(创建后不能被修改);

5、final修饰的引用(对象句柄/引用/指针)

final会将句柄变为一个常数,固定到一个具体对象,不再只想其他对象,但对象值可变。(这一限制也适用于数组,数组也属于对象,数组本身也是可以修改的)

6、final修饰的方法参数中的final句柄

意味着在该方法内部,我们不能改变参数句柄指向的实际东西,也就是说在方法内部不能给形参句柄再另外赋值。

2.2 final的内存语义

对于final域,编译器和处理器要遵循两个重排序规则
  
  1.写final重排约束:在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。
  
  2.读final重拍约束:初次读一个包含final域的对象的应用,与随后初次读这个final域,这两个操作之间不能重排序。

在这里插入图片描述

3 static final

1、static final 修饰的属性

强调它们只有一个,final修饰的属性表明是一个常数(创建后不能被修改)。static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问。

2、static final修饰的方法

表示该方法不能重写,可以在不new对象的情况下调用

4 static\final\static final区别

  • static修饰的属性强调它们只有一个;
  • final修饰的属性表明是一个常数,不可改变(创建后不能被修改)。
  • static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问。
    static final也可以修饰方法,表示该方法不能重写,可以在不new对象的情况下调用。

static final和final static没什么区别,一般static写在前面。
private/public static final 和static final区别只是访问权限不同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值