Java中的“static“关键字

写在前面

前阵子看到一篇有关于Java中static的使用和介绍,讲的比较全面。近几日忽然想起早先工作碰到的有关static的相关问题,自己也总结一下吧。

static是我们项目中经常用到的关键字,也是Java中非常重要的一个关键字,static可以修饰变量、方法、做静态代码块、静态导包等,下面我们就来具体聊一聊这个关键字。

开始

一提到static的时候,第一时间你会想到什么?!对了你可能第一时间就能想到main方法,main方法为什么是static修饰的???如果你不太清楚,带着疑问继续向下看吧。

static修饰变量

static的意思是什么?你会脱口而出“静态”,static关键字表示的概念就是“全局的,静态的”大概的意思,用它修饰的变量我们都会称作为“静态变量”。

在这里插入图片描述
静态变量也被称作为类变量,static修饰过的变量是属于这个类所有的。是不是有点不太明白什么意思?这其实就是说,static关键字只能定义在类中,而不能定义在方法中。请看下面的截图:
在这里插入图片描述
在这里插入图片描述
从上图可以看到,很明显不能在方法中定义static变量,即使给方法加上static也不行。

既然static修饰的变量是属于这个类所有,那么就可以直接通过类来直接调用static修饰的变量,它不需要手动实例化类进行调用(即:类名.静态变量)。如下图:(必要时您还得注意变量的public或者private等,这里我们不讨论了。)

在这里插入图片描述
static修饰的变量有何用途

早先在我们的项目中曾经如此应用static修饰的变量,就是项目启动的时候,我们加载一些重要的系统数据,如不常修改的数据,字典数据等,加载赋值到一个类的static修饰的变量,大家都知道static修饰的变量在赋值之后,如果不对它进行第二次赋值,它的数据将一直保持第一次赋值的数据,直到服务器停止,这样方便数据调用。当然还有其他应用,我们也不做研究了。

有关于变量的几个概念:

  • 定义在方法,代码块,构造方法的变量被称为成员变量。
  • 定义在方法,代码块,构造方法的变量被称为局部变量。
  • 定义在方法参数的变量称作参数。

static修饰方法

static修饰方法,被static修饰的方法我们称作为“静态方法”,其实说白了就是在一个方法上加上static关键字进行修饰。在没有创建任何对象的前提下,通过类本身来就可以调用static修饰的方法,我们平时也把static修饰的方法叫做这个类的类方法,实际上是static方法的主要用途。

在这里插入图片描述
如上图所示,“staticFunction”是static修饰的静态方法,所以可以直接使用“类名.方法名”进行调用,这个调用其实就和之前咱们说的“类名.变量名”的调用方式,是一个道理。

static修饰方法讲到这里了,你大概就应该清楚了main方法为什么是用static修饰的了。很明显,因为程序执行main方法的时候没有创建任何对象,因此只能通过类名来访问,所以main方法用static修饰。

那通过这个static修饰main方法,我们其实也可以延伸一下技术,就是单例模式。熟悉单例模式的都知道,单例模式就是和static修饰的方法有关系,这里我们不做研究了,有兴趣的小伙伴可以点击进入Java中的单例模式

static修饰方法的注意

  • 第一恶就是最上面刚说的,不用创建对象,直接类名.变量名即可调用和访问。
  • static修饰的方法内部是不能调用非静态方法的。
  • 非静态方法内部是可以调用static静态方法。

static修饰代码块

首先代码块是分为两种的,一种是使用{ }代码块,另外一种就是用static{ }的,我们称作“静态代码块”。static静态代码块是可以放在一个类的任何地方,还可以有多个static静态代码块。类初次被加载的时候,会按照static静态代码块的顺序来执行,每个static静态代码块只能执行一次,而且还是在类加载的时候就只执行一次。

在这里插入图片描述
执行结果:

hi static1 run
hi static3 run
hi static2 run
staticFunction is run

如上图代码和结果,可以看到static静态代码块可以有多个,可以放在任意位置,而且是在类加载的时候只执行一次,而且还是自上而下顺序执行。

static用作静态内部类

在说静态内部类之前,我们先普及一下内部类的分类,一共分为普通内部类、局部内部类、静态内部类、匿名内部类四种。说白了,静态内部类就是用static修饰的内部类,静态内部类可以包含静态成员变量,也可以包含非静态成员变量,但是在非静态内部类中不可以声明静态成员变量。

静态内部类有许多作用,由于非静态内部类的实例创建需要有外部类对象的引用,所以非静态内部类对象的创建必须依托于外部类的实例,而静态内部类的实例创建只需依托外部类,并且由于非静态内部类对象持有了外部类对象的引用,因此非静态内部类可以访问外部类的非静态成员,而静态内部类只能访问外部类的静态成员。

由于静态内部类用的较少,我们不做过多阐述了,如果您有兴趣可以移步Java中的内部类

静态导入包

首先我们平时在用到一个类的时候,比如用到ArrayList,我们就需要导入java.util.ArrayList,那我们的代码就是“import java.util.ArrayList;”,再简单不过了。那什么是静态导入包?静态导入包就是使用“import static”用来导入某个类或者某个包中的静态方法或者静态变量。

在这里插入图片描述在这里插入图片描述

大家上看以上代码,首先我定义了一个类叫“StaticDemo”,其中我定义了静态变量“i”和静态方法“test”。然后我在第二个类“StaticTest”中,我利用“import static”的方式导入了“StaticDemo”的所有有关静态的变量和方法,然后我就可以直接进行调用了。看到这好像并没有特殊的地方,感觉就像多一此举,直接用“类名.变量”或者“类名.方法”不就行了,对你说的没错,我们这里只是讲什么是静态导入包。

static变量的生命周期

static变量的生命周期与类的生命周期相同,随类的加载而创建,随类的销毁而销毁;普通成员变量和其所属的生命周期相同。其实到这就是文章最开始的地方我说的那个静态变量的用途就是利用了这一点。

static和序列化

Java的序列化简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。

但是static修饰的变量不能被序列化,static成员不属于对象实例,属于类级别的,所以不能序列化,当然也可以用“transient”定义来强制不能序列化。

static经常用作日志打印

private static final Logger LOG = LogFactory.getLogger("StaticTest.class");

以上代码我想大家是经常看到吧,打印日志。当然去掉“final”和“static”是没有问题的,都可以运行,都是可以打印日志。但是很明显去掉了“final”和“static”之后,对于每个类的实例化对象都会拥有一个“LOG”,那创建了100个、1000个或者更多类的实例对象,则会多出100个、1000个甚至更多的“Logger”对象,不多说了,肯定会造成资源的浪费.因此通常会将“Logger”对象声明为static,这样能减少对内存资源的占用。

最后一个令人想不到的问题“类的构造器(构造方法)是否是static的?”

这个问题谁没事干了琢磨这个去,说实话我也不知道,但是我隐约记得我一个老师曾经告诉过我“构造器(构造方法)虽然没有用static修饰,但是实际上是static的”,那为什么构造器(构造方法)不能加“static”修饰?构造器(构造方法)是为了初始化对象的,用来生成实例,那就不能用“static”修饰,还有就是刚才说的,它本身就是“static”,那么既然是“static”的为什么还能用来实例化对象?!这个???!!!,emmm!!!???,有兴趣的朋友可以自行研究研究了。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WorkLee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值