当前位置: 首页 > news >正文

【面试真题拆解】Java的Static关键字到底怎么用?

面试官上来就问:

“ 那个Java里面的Static关键字,一般是怎么用?”

一句话:

Static是“类级别的”,不是“实例级别的”。

被Static修饰的东西,属于整个类,所有实例共用一份,不用new对象就能直接用;

而没被Static修饰的东西,属于单个实例,每个实例有自己的一份,必须new对象才能用。

对比项静态(Static)实例(非Static)
归属属于整个类属于单个实例
内存位置方法区(JDK8 之后叫元空间)堆内存
访问方式类名.(变量/方法),或(实例.变量/方法)(不推荐)必须通过实例.变量/方法访问
共享性所有实例共用一份每个实例有自己的一份
初始化时机类加载时初始化创建实例时初始化
访问限制只能直接访问静态成员可以访问静态成员和实例成员

1. 静态变量

静态变量就像是整个类共享的“公共储物柜”,所有实例共用这一个柜子,你放进去的东西,别人也能拿到;而实例变量是每个实例自己的“私人储物柜”,互不干扰。

举个例子,用静态变量做全局计数器
/** * 网站访问计数器 */publicclassWebsiteCounter{// 静态变量:所有实例共用,统计总访问次数publicstaticinttotalVisitCount=0;// 实例变量:每个实例自己的,统计单个用户的访问次数publicintuserVisitCount=0;/** * 访问方法 */publicvoidvisit(){// 修改静态变量:总访问次数+1totalVisitCount++;// 修改实例变量:单个用户访问次数+1userVisitCount++;}publicstaticvoidmain(String[]args){// 用户1访问WebsiteCounteruser1=newWebsiteCounter();user1.visit();user1.visit();System.out.println("用户1访问次数:"+user1.userVisitCount);// 输出2System.out.println("总访问次数:"+WebsiteCounter.totalVisitCount);// 输出2// 用户2访问WebsiteCounteruser2=newWebsiteCounter();user2.visit();System.out.println("用户2访问次数:"+user2.userVisitCount);// 输出1System.out.println("总访问次数:"+WebsiteCounter.totalVisitCount);// 输出3}}

2. 静态方法

静态方法是属于类的“公共工具”,不用new对象,直接通过【类名.方法名】就能调用,而实例方法是属于单个实例的,必须new对象之后才能调用。

举个例子,用静态方法做工具类
/** * 字符串工具类 */publicclassStringUtils{// 私有构造方法:从根源上禁止外部代码 new StringUtils()// 工具类全是静态方法,完全不需要实例化,这样做能强制大家用[类名.方法名]的正确用法privateStringUtils(){}/** * 静态方法:判断字符串是否为空 */publicstaticbooleanisEmpty(Stringstr){returnstr==null||str.trim().isEmpty();}/** * 静态方法:字符串反转 */publicstaticStringreverse(Stringstr){if(isEmpty(str)){returnstr;}returnnewStringBuilder(str).reverse().toString();}publicstaticvoidmain(String[]args){// 直接通过类名调用静态方法,不用new对象System.out.println(StringUtils.isEmpty(""));// 输出trueSystem.out.println(StringUtils.reverse("hello"));// 输出olleh}}

3. 静态代码块

静态代码块是类加载的时候执行一次,且只执行一次的代码块,用来初始化静态变量或者做一些类级别的准备工作(比如加载配置文件、初始化数据库连接池)。

举个例子,用静态代码块初始化静态配置
/** * 配置类 */publicclassConfig{// 静态变量:数据库连接地址publicstaticStringdbUrl;publicstaticStringdbUsername;publicstaticStringdbPassword;// 静态代码块:类加载时执行一次,初始化静态变量static{System.out.println("静态代码块执行,开始初始化配置...");// 模拟从配置文件读取配置dbUrl="jdbc:mysql://localhost:3306/test";dbUsername="root";dbPassword="123456";}// 实例代码块:创建实例时执行,每次new都执行{System.out.println("实例代码块执行...");}// 构造方法:创建实例时执行,每次new都执行publicConfig(){System.out.println("构造方法执行...");}publicstaticvoidmain(String[]args){// 第一次访问Config类,触发类加载,静态代码块执行System.out.println("数据库地址:"+Config.dbUrl);System.out.println("---");// new第一个实例,实例代码块和构造方法执行newConfig();System.out.println("---");// new第二个实例,实例代码块和构造方法执行,但静态代码块不再执行newConfig();}}
小贴士

静态代码块只在类第一次被加载时执行一次,之后不管new多少个实例,都不会再执行。

4. 静态内部类

静态内部类是属于外部类的“独立房间”,不用依赖外部类的实例就能直接创建,而非静态内部类是属于外部类实例的“附属房间”,必须先有外部类实例才能创建。

静态内部类的作用是:

利用 Java 的类加载时机,实现了懒加载(用的时候才创建)+ 线程安全(JVM 保证)+ 不用加锁(性能高)的完美单例。

举个例子,用静态内部类实现线程安全的单例模式
/** * 单例模式:静态内部类实现 */publicclassSingleton{// 私有构造方法:从根源上禁止外部代码直接 new Singleton()privateSingleton(){}// 静态内部类:只有第一次被访问时才会加载(实现懒加载,用的时候才创建实例,不占内存)// 因为是在 Singleton 类内部,所以可以访问上面的 private 构造方法privatestaticclassSingletonHolder{// 静态变量:JVM 类加载过程是天然线程安全的,这里初始化唯一的单例实例(不用加锁,性能高)privatestaticfinalSingletonINSTANCE=newSingleton();}// 全局唯一的访问点:外部代码只能通过这里获取单例实例publicstaticSingletongetInstance(){returnSingletonHolder.INSTANCE;}publicstaticvoidmain(String[]args){// 获取单例实例Singletoninstance1=Singleton.getInstance();Singletoninstance2=Singleton.getInstance();// 两个实例是同一个,完美实现单例System.out.println(instance1==instance2);// 输出true}}

小贴士

  • 静态变量存放在JVM的方法区(元空间),不是堆内存。
  • 静态变量可以通过【类名.变量名】直接访问,也可以通过【实例.变量名】访问(不过,不推荐,因为容易混淆)。
  • 因为所有线程共用同一个静态变量,多线程同时修改会出现并发问题,需要加锁保证线程安全。
  • 因为实例变量和方法依赖具体的实例,静态方法调用时可能还没new对象,所以,静态方法只能直接访问静态变量和静态方法,不能直接访问实例变量和实例方法。
  • this 代表当前实例,静态方法属于类,调用时可能还没创建实例,this 根本不存在,所以,静态方法不能用 this。
  • 静态内部类只能直接访问外部类的静态变量和静态方法,不能直接访问实例变量和实例方法。
http://www.jsqmd.com/news/519343/

相关文章:

  • 3月18日笔记
  • Cookie操作避坑指南:从浏览器复制到Python requests的完整流程解析
  • 保姆级教程:用OpenWRT打造企业级访客WiFi(含防火墙规则+DHCP避坑指南)
  • Xilinx MMCM动态相位调整:从原理到实战的时钟微调指南
  • 信息学奥赛必备:5分钟搞定配对碱基链的两种C++解法(附完整代码)
  • 从PID到深度学习:柔性机器人控制算法演进全解析(附Python示例代码)
  • 从键盘到显示屏:给STM32F4计算器加个OLED界面(I2C驱动教程)
  • 揭示提示工程架构师创新实验室的神秘面纱
  • PyQt5桌面应用内嵌Web地图避坑指南:从QWebEngineView加载到JS交互全流程
  • 华为OceanStor存储管理员密码遗忘?一文详解从串口到Web的完整重置路径
  • Pixel 2XL刷机指南:从AOSP源码编译到烧录的完整流程(附常见错误解决)
  • 基于PLC的煤矿皮带运输机控制系统 plc煤矿皮带运输机采用西门子博途s7-1200编程
  • TPS63000高效DC-DC电源芯片技术规格:调节宽电压范围至最高电压高达效率实现负载断开自...
  • React - React-intl中injectIntl的作用?
  • FineReport报表JS实现动态参数传递与对话框报表交互
  • Supervisor配置文件里environment变量怎么填?一个变量多个路径的实战写法
  • Python自动化界面操作:从基础到实战全攻略
  • 【51单片机实战】波形发生器DIY:从原理图到四种波形输出全解析
  • Claude Code 2.1.x vs Cursor 2.6.x:最强编程模型对决(2026年3月)
  • React - React Intl 使用指南
  • 2026年大模型选型指南:GPT、Gemini、Claude谁更适合你?
  • 基于虚拟矢量与FOC控制算法的死区补偿仿真模型:m文件编写SVPWM与死区补偿算法研究与应用
  • claude code 的三种 skill 类型以及一些常见陷阱
  • Unity:Cinemachine Virtual Camera(虚拟摄像机)的智能追踪艺术
  • 打工人必备!用Coze把微信/邮箱发票自动同步到飞书表格(避坑指南)
  • 《信息服务与应用》 第三章 研究方法及应用
  • 新手避坑指南:FileZilla连接Linux报错‘拒绝连接’的5种解决方法(附SSH完整配置流程)
  • 实测对比后 8个AI论文写作软件:本科生毕业论文与科研写作必备工具推荐
  • 内网环境搞定OpenResty离线安装:从依赖包下载到避坑全记录
  • 佛山宏昭自动化技术有限公司是做什么的?主营产品、业务范围及服务优势全解析