面试官:兄弟,说说Java的static关键字吧
读者乙在上一篇我去系列文章里留言说,“我盲猜下一篇标题是,‘我去,你竟然不知道 static 关键字’”。我只能说乙猜对了一半,像我这么有才华的博主,怎么可能被读者猜中了心思呢,必须搞点不一样的啊,所以本篇文章的标题你看到了。

七年前,我从美女很多的苏州回到美女也不少的洛阳,抱着一幅“从二线城市退居三线城市”的心态,投了不少简历,也“约谈”了不少面试官,但仅有两三个令我感到满意。其中有一位叫老马,至今还活在我的微信通讯录里。他当时扔了一个面试题把我砸懵了:“兄弟,说说 Java 的 static 关键字吧。”
我那时候二十三岁,正值青春年华,自认为所有的面试题都能对答如流,结果没想到啊,被“刁难”了——原来洛阳这块互联网的荒漠也有技术专家啊。现在回想起来,脸上不自觉地泛起了羞愧的红晕:主要是自己当时太菜了。
不管怎么说,经过多年的努力,我现在的技术功底已经非常扎实了,有能力写篇文章剖析一下 Java 的 static 关键字了——只要能给初学者一些参考,我就觉得非常满足。
先来个提纲挈领(唉呀妈呀,成语区博主上线了)吧:
static 关键字可用于变量、方法、代码块和内部类,表示某个特定的成员只属于某个类本身,而不是该类的某个对象。
01、静态变量
静态变量也叫类变量,它属于一个类,而不是这个类的对象。
public class Writer {
private String name;
private int age;
public static int countOfWriters;
public Writer(String name, int age) {
this.name = name;
this.age = age;
countOfWriters++;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
其中,countOfWriters 被称为静态变量,它有别于 name 和 age 这两个成员变量,因为它前面多了一个修饰符 static。
这意味着无论这个类被初始化多少次,静态变量的值都会在所有类的对象中共享。
Writer w1 = new Writer("沉默王二",18);
Writer w2 = new Writer("沉默王三",16);
System.out.println(Writer.countOfWriters);
按照上面的逻辑,你应该能推理得出,countOfWriters 的值此时应该为 2 而不是 1。从内存的角度来看,静态变量将会存储在 Java 虚拟机中一个名叫“Metaspace”(元空间,Java 8 之后)的特定池中。
静态变量和成员变量有着很大的不同,成员变量的值属于某个对象,不同的对象之间,值是不共享的;但静态变量不是的,它可以用来统计对象的数量,因为它是共享的。就像上面例子中的 countOfWriters,创建一个对象的时候,它的值为 1,创建两个对象的时候,它的值就为 2。
简单小结一下:
1)由于静态变量属于一个类,所以不要通过对象引用来访问,而应该直接通过类名来访问;

2)不需要初始化类就可以访问静态变量。
public class WriterDemo {
public static void main(String[] args) {
System.out.println(Writer.countOfWriters); // 输出 0
}
}
02、静态方法
静态方法也叫类方法,它和静态变量类似,属于一个类,而不是这个类的对象。
public static void setCountOfWriters(int countOfWriters) {
Writer.countOfWriters = countOfWriters;
}
setCountOfWriters() 就是一个静态方法,它由 static 关键字修饰。
如果你用过 java.lang.Math 类或者 Apache 的一些工具类(比如说 StringUtils)的话,对静态方法一定不会感动陌生。

Math 类的几乎所有方法都是静态的,可以直接通过类名来调用,不需要创建类的对象。

简单小结一下:
1)Java 中的静态方法在编译时解析,因为静态方法不能被重写(方法重写发生在运行时阶段,为了多态)。
2)抽象方法不能是静态的。

3)静态方法不能使用 this 和 super 关键字。
4)成员方法可以直接访问其他成员方法和成员变量。
5)成员方法也可以直接方法静态方法和静态变量。
6)静态方法可以访问所有其他静态方法和静态变量。
7)静态方法无法直接访问成员方法和成员变量。

03、静态代码块
静态代码块可以用来初始化静态变量,尽管静态方法也可以在声明的时候直接初始化,但有些时候,我们需要多行代码来完成初始化。
public class StaticBlockDemo {
public static List<String> writes = new ArrayList<>();
static {
writes.add("沉默王二");
writes.add("沉默王三");
writes.add("沉默王四");
System.out.println("第一块");
}
static {
writes.add("沉默王五");
writes.add("沉默王六");
System.out.println("第二块");
}
}
writes 是一个静态的 ArrayList,所以不太可能在声明的时候完成初始化,因此需要在静态代码块中完成初始化。
简单小结一下:
1)一个类可以有多个静态代码块。
2)静态代码块的解析和执行顺序和它在类中的位置保持一致。为了验证这个结论,可以在 StaticBlockDemo 类中加入空的 main 方法,执行完的结果如下所示:
第一块
第二块
04、静态内部类
Java 允许我们在一个类中声明一个内部类,它提供了一种令人信服的方式,允许我们只在一个地方使用一些变量,使代码更具有条理性和可读性。
常见的内部类有四种,成员内部类、局部内部类、匿名内部类和静态内部类,限于篇幅原因,前三种不在我们本次文章的讨论范围,以后有机会再细说。
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
public static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
以上这段代码是不是特别熟悉,对,这就是创建单例的一种方式,第一次加载 Singleton 类时并不会初始化 instance,只有第一次调用 getInstance() 方法时 Java 虚拟机才开始加载 SingletonHolder 并初始化 instance,这样不仅能确保线程安全也能保证 Singleton 类的唯一性。不过,创建单例更优雅的一种方式是使用枚举。
简单小结一下:
1)静态内部类不能访问外部类的所有成员变量。
2)静态内部类可以访问外部类的所有静态变量,包括私有静态变量。
3)外部类不能声明为 static。

学到了吧?学到就是赚到。
我是沉默王二,一枚有趣的程序员。如果觉得文章对你有点帮助,请微信搜索「 沉默王二 」第一时间阅读,回复【666】更有我为你精心准备的 500G 高清教学视频(已分门别类)。
本文 GitHub 已经收录,有大厂面试完整考点,欢迎 Star。
原创不易,莫要白票,请你为本文点个赞吧,这将是我写作更多优质文章的最强动力。
面试官:兄弟,说说Java的static关键字吧的更多相关文章
- Java面试官最爱问的volatile关键字
在Java的面试当中,面试官最爱问的就是volatile关键字相关的问题.经过多次面试之后,你是否思考过,为什么他们那么爱问volatile关键字相关的问题?而对于你,如果作为面试官,是否也会考虑采用 ...
- 最后一面挂在volatile关键字上,面试官:重新学学Java吧!
最后一面挂在volatile关键字上,面试官:重新学学Java吧! 为什么会有volatile关键字? volatile: 易变的; 无定性的; 无常性的; 可能急剧波动的; 不稳定的; 易恶化的; ...
- java中static关键字的作用
java中static关键字主要有两种作用: 第一:为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关. 第二,实现某个方法或属性与类而不是对象关联在一起 简单来说,在Java语言中,s ...
- Java的static关键字
本文参考:Java的static关键字 通过static关键字可以满足两方面的需要.一种情形是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多少对象,甚至根本就不创建任何对象.另一种情形是,希 ...
- java的static关键字 – Break易站
本文内容来自:java的static关键字 – Break易站 (原文网站阅读体验更好) 通过static关键字可以满足两方面的需要.一种情形是,只想为某特定域分配单一存储空间,而不去考虑究竟要创建多 ...
- Java面向对象-static关键字、静态方法与普通方法、静态成员变量
Java面向对象-static关键字.静态方法与普通方法 static关键字的基本作用:方便在没有创建对象的情况下来进行调用(方法/变量). 很显然,被static关键字修饰的方法或者变量不需要依赖于 ...
- 【JAVA秒会技术之秒杀面试官】秒杀Java面试官——集合篇(一)
[JAVA秒会技术之秒杀面试官]秒杀Java面试官——集合篇(一) [JAVA秒会技术之秒杀面试官]JavaEE常见面试题(三) http://blog.csdn.net/qq296398300/ar ...
- Java 静态static关键字,main函数,对象的初始化过程,对象调用成员,单例模式的设计,静态代码块(6)
Java 静态static关键字,静态代码块详情参考:static的使用原理讲解http://www.cnblogs.com/itcqx/p/5519464.html main函数: java Mai ...
- Java:static关键字小记
Java:static关键字小记 对 Java 中的 static 关键字,做一个微不足道的小小小小记 static 修饰变量 静态变量:是被 static 修饰的变量,也称为类变量,它属于类,因此不 ...
随机推荐
- 【FPGA篇章六】FPGA编译向导:详解编译预处理功能
欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章 Verilog HDL语言和C语言一样也提供了编译预处理功能. Verilog HDL允许在程序中使用特殊的编译预处理语句. 在编译时,通常 ...
- Qt之connect
Qt4之connect 基本用法 connect(ui->toolButton, SIGNAL(clicked()), this, SLOT(OnClickButton())); disconn ...
- Java的Object.wait(long)在等待时间过去后会继续往后执行吗
Java的Object.wait(long)在等待时间过去后会继续往后执行吗 Object.wait(long)方法相比于wait,多了个等待时长,那么当等待时长过去后,线程会继续往下执行吗? 单个线 ...
- 流媒体与实时计算,Netflix公司Druid应用实践
Netflix(Nasdaq NFLX),也就是网飞公司,成立于1997年,是一家在线影片[租赁]提供商,主要提供Netflix超大数量的[DVD]并免费递送,总部位于美国加利福尼亚州洛斯盖图.199 ...
- 多线程高并发编程(8) -- Fork/Join源码分析
一.概念 Fork/Join就是将一个大任务分解(fork)成许多个独立的小任务,然后多线程并行去处理这些小任务,每个小任务处理完得到结果再进行合并(join)得到最终的结果. 流程:任务继承Recu ...
- abp web.mvc项目中的菜单加载机制
abp中的菜单加载机制 在abp中菜单的定义与我们传统写的框架不一样,它是在编写代码的时候配置,而我们一般写的通用权限管理系统中,是后期在后台界面中添加的.这一点有很大不同.abp关于菜单的定义及管理 ...
- 高通Vuforia(Unity3D)云识别初级使用教程
高通Vuforia(Unity3D)云识别初级使用教程 最近因项目开发需要,接触了高通的AR引擎Vuforia云识别,个人感觉稳定性还是很不错的,唯一不爽的地方就是免费的云识别库每个月只能识别10 ...
- React-Redux填坑
这篇东西以后慢慢补充. Q:今天遇到一个问题是 TypeError:dispatch is not a function A:一直报这个type error,调试了好一阵,最后在tof上看到网友说co ...
- 聚类算法——DBSCAN算法原理及公式
聚类的定义 聚类就是对大量未知标注的数据集,按数据的内在相似性将数据集划分为多个类别,使类别内的数据相似度较大而类别间的数据相似度较小.聚类算法是无监督的算法. 常见的相似度计算方法 闵可夫斯基距离M ...
- deno+mongo实战踩坑记
自从 deno 1.0 发布以来,有关 deno 的文章很多,大多数都是在讨论怎么安装 deno .deno 有哪些特点 .deno 和 node 有哪些异同.deno是不是 node 的替代品等.咱 ...