热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Java修饰符之三】Java中static关键字的五种使用方法

static关键字五种用法的总结平时我们都会很经常的去使用static关键字去修饰变量呀,方法呀,都大概的知道被static所修饰之后,有

static关键字五种用法的总结



平时我们都会很经常的去使用static关键字去修饰变量呀,方法呀,都大概的知道被static所修饰之后,有一种“全局”的味道,那么我就在这里详细的总结一下static关键字的四种用法。有问题欢迎留言

  • 修饰成员变量
  • 修饰成员方法
  • 修饰代码块
  • 修饰内部类
  • 静态导包


修饰成员变量



注意:
首先声明一下,这里所修饰的是成员变量,而不是局部变量,局部变量是不允许被static修饰的。(了解成员变量和局部变量的概念和区别)

通常我们在开发过程中,用static去修饰一个成员变量,是为了声明一个全局变量,让它对该类的所有对象共享。或者配合final关键字声明一个全局的常量。被static所修饰的成员变量称为静态变量(或类变量),是属于类的范畴。没有被static修饰的变量称为实例变量,属于对象的范畴。

静态变量特性:

  • 全局共享,该类的所有实例对象都可以引用到同一个静态变量。
  • 别的类可以通过类名.变量名去调用该静态变量
  • 静态变量不同于实例变量,静态变量存放在内存的方法区中,而实例变量存放在堆中
  • 静态变量在类加载的时候被加载,在程序运行期间有且仅加载一次

代码测试:
以下是测试代码,我们从JVM内存模型来分析一下,静态变量和实例变量在内存中区别

public class Student {//实例变量String name;int age;//成员方法public String toString() {return "Student [name=" + name + ", age=" + age + "]";}public static void main(String[] args) {//声明两个Student类型的变量s1,s2,分别为这两个变量赋于两个Student实例对象的地址Student s1 = new Student();s1.name = "Tom";s1.age = 22;Student s2 = new Student();s2.name = "Jerry";s2.age = 31;}
}

此刻的内存模型为:
这里写图片描述
从上图和测试代码结合来看,我们可以看出,s1s2两个实例变量所指向的实例对象都存储在堆中。实例变量nameage都属于对象的数据,对象的变量应该交给对象自己去管理,所以实例变量是存储在堆的对象当中。

接下来,我们在稍微修改一下代码,用static修饰age变量,使其成为静态变量(类变量)

public class Student {String name;static int age; //使用static修饰符修饰age变量public String toString() {return "Student [name=" + name + ", age=" + age + "]";}public static void main(String[] args) {Student s1 = new Student();s1.name = "Tom";s1.age = 22;Student s2 = new Student();s2.name = "Jerry";s2.age = 31;}
}

此刻的内存模型为:
这里写图片描述
从图中内存模型中,我们可以看出,静态变量age不再交给对象管理,堆中Student对象的数据也不再含有age这个变量。因为静态变量是属于类的一部分,与对象无关,所以age变量会统一交给Student类去管理,既存储在方法区(静态区)中。这也印证了静态变量是属于该类所有对象所共享的,静态变量被改变,是对该类所有对象可见的。

补充:

  • Student类型的局部变量s1和s2是存储在虚拟机栈中的,所储存的值是所指向对象的地址,该变量称为”引用”或”对象的引用”
  • 堆中对象的方法空间所存放的值是方法区类信息中具体方法的地址,所以同类的不同对象,同一个方法都是指向同一个地址的,既方法区具体方法的地址。如s1对象和s2对象存放toString方法的空间实际存放的是方法区中Student类的toString方法的地址,他们所引用的都是同一片地址。
  • 方法区所存放的类的信息可以说是类的定义,实例化的实际流程就是根据方法区中类的信息去实例化出具体的对象,然后将这个对象的存放在堆中。


修饰成员方法



使用static来修饰方法,相比于修饰成员变量,修饰方法对于数据的存储方面并没有多大的变化,因为方法本身就是存放在类的定义当中的,既方法区类的信息中。但是静态方法还是有作用的,比如可以使用类名.方法名的方式操作方法,避免了要new对象的资源消耗,静态方法的应用在工具类中经常被使用到,同时在JDK8新特性(接口的增强)中,可以在接口中使用static去修饰的具体方法,从而使得接口拥有具体的方法。

public class Demo {public static int add(int a ,int b){return a + b ; }
}class Test {public static void main(String[] args) {System.out.println(Demo.add(1, 2));}
}

特性:

  • 可以使用类名.方法名去调用方法
  • 静态方法不允许直接调用非静态成员,因为在类的加载中,静态成员在类加载时优先级高于非静态成员(实例变量,非静态方法等)。所以总不能在静态方法已经被JVM加载识别的时候,方法体内存在着一个未知的东西(因为还没有被JVM所加载识别)。
  • 静态方法体内不允许使用this,super关键字。因为静态方法属于类的范畴,是通过类名.方法名进行调用的,不需要实例化出对象来调用,所以不存在对象这个概念.但thissuper是属于对象的概念范畴,this代表着当前对象,super代表当前对象的父类对象。


修饰代码块



static只允许修饰构造代码块(在类中,方法体外的代码块),被static修饰的代码块称为静态代码块。静态代码块的一大作用是帮助类进行的静态变量的初始化。在类加载的优先级与静态变量相同,谁先加载,只看实际代码位置。

public class Demo{static a ;static { a = 1;System.out.println(a);}
}

补充:
【Java学习笔记系列】继承方式下静态成员变量、普通成员变量、静态代码块、构造代码块、构造函数在JVM的加载顺序


修饰内部类



我们知道内部类分为四种,有成员内部类,静态内部类,局部内部类和匿名内部类。而静态内部类就是被static所修饰的内部类。我们这里要声明一下,只允许能被static修饰的类只有两种:

  • 顶级类下的内部类
  • 静态内部类下的内部类


public class OuterClass {//顶级类(top-level class)下的内部类能被static修饰public static class InnerClass {//静态内部类下的内部类能被static修饰publis static class InnerClassB{}}
}

特性:

  • 被static所修饰的内部类称为静态内部类
  • 静态内部类切断了与其外部类对象之间的联系。

如果对内部类不够了解并想了解静态内部类的详细特性,可以看我这篇博文:
【Java学习笔记系列】深入学习Java的内部类以及内部类相关知识点总结

静态导包



静态导包的方式使用的比较少,博主我也是在查看static的资料的情况下,才发现这种用法的,这里就不进行啰嗦了,大家可以到我下面列的参考网站查看静态导包的讲解。
[java]static关键字的四种用法


我的其他修饰符总结直链:
【Java修饰符之一】Java中Default关键字的两种使用方法
【Java修饰符之二】探讨Java中final的三种使用场景和总结
【Java修饰符之三】Java中static关键字的五种使用方法


参考资料:
[java]static关键字的四种用法
Java中的static关键字解析

在此谢谢查询和参考过的网站和博客的作者,感谢你们的知识!


以下是之前总结的两编关于修饰符的总结:
【Java修饰符笔记之一】Java中Default关键字的两种使用方法
【Java修饰符笔记之二】探讨Java中final的使用场景和总结


推荐阅读
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 深入理解 Java 控制结构的全面指南 ... [详细]
  • 在Android应用开发中,实现与MySQL数据库的连接是一项重要的技术任务。本文详细介绍了Android连接MySQL数据库的操作流程和技术要点。首先,Android平台提供了SQLiteOpenHelper类作为数据库辅助工具,用于创建或打开数据库。开发者可以通过继承并扩展该类,实现对数据库的初始化和版本管理。此外,文章还探讨了使用第三方库如Retrofit或Volley进行网络请求,以及如何通过JSON格式交换数据,确保与MySQL服务器的高效通信。 ... [详细]
  • Android中将独立SO库封装进JAR包并实现SO库的加载与调用
    在Android开发中,将独立的SO库封装进JAR包并实现其加载与调用是一个常见的需求。本文详细介绍了如何将SO库嵌入到JAR包中,并确保在外部应用调用该JAR包时能够正确加载和使用这些SO库。通过这种方式,开发者可以更方便地管理和分发包含原生代码的库文件,提高开发效率和代码复用性。文章还探讨了常见的问题及其解决方案,帮助开发者避免在实际应用中遇到的坑。 ... [详细]
  • 在使用SSH框架进行项目开发时,经常会遇到一些常见的问题。例如,在Spring配置文件中配置AOP事务声明后,进行单元测试时可能会出现“No Hibernate Session bound to thread”的错误。本文将详细探讨这一问题的原因,并提供有效的解决方案,帮助开发者顺利解决此类问题。 ... [详细]
  • 本文介绍了如何在iOS平台上使用GLSL着色器将YV12格式的视频帧数据转换为RGB格式,并展示了转换后的图像效果。通过详细的技术实现步骤和代码示例,读者可以轻松掌握这一过程,适用于需要进行视频处理的应用开发。 ... [详细]
  • 本文探讨了 Java 中 Pair 类的历史与现状。虽然 Java 标准库中没有内置的 Pair 类,但社区和第三方库提供了多种实现方式,如 Apache Commons 的 Pair 类和 JavaFX 的 javafx.util.Pair 类。这些实现为需要处理成对数据的开发者提供了便利。此外,文章还讨论了为何标准库未包含 Pair 类的原因,以及在现代 Java 开发中使用 Pair 类的最佳实践。 ... [详细]
  • 本文详细探讨了Java事件处理机制的核心概念与实现原理,内容浅显易懂,适合初学者逐步掌握。通过具体的示例和详细的解释,读者可以深入了解Java事件模型的工作方式及其在实际开发中的应用。 ... [详细]
  • 在Android开发过程中,序列化是一个重要的概念,尤其是在数据传输和存储时。本文详细解析了Parcelable序列化的原理及其应用场景,并对比了其他序列化方式,如Serializable。通过具体的实例和代码示例,帮助开发者更好地理解和掌握Parcelable的使用方法,避免在实际开发和面试中遇到相关问题。 ... [详细]
  • 在 Java 中,守护线程是一种特殊的后台线程,类似于操作系统中的后台进程。其主要特点是当所有非守护线程都结束时,守护线程会自动终止。这种机制使得守护线程非常适合用于执行一些辅助性的任务,如垃圾回收、日志记录等。通过设置线程为守护线程,可以确保在应用程序的主要任务完成后,这些辅助任务能够自动停止,从而避免资源浪费。例如,可以通过 `Thread.setDaemon(true)` 方法将线程设置为守护线程。 ... [详细]
  • 本文详细探讨了MySQL数据库实例化参数的优化方法及其在实例查询中的应用。通过具体的源代码示例,介绍了如何高效地配置和查询MySQL实例,为开发者提供了有价值的参考和实践指导。 ... [详细]
  • 在前文探讨了Spring如何为特定的bean选择合适的通知器后,本文将进一步深入分析Spring AOP框架中代理对象的生成机制。具体而言,我们将详细解析如何通过代理技术将通知器(Advisor)中包含的通知(Advice)应用到目标bean上,以实现切面编程的核心功能。 ... [详细]
  • SQLite数据库CRUD操作实例分析与应用
    本文通过分析和实例演示了SQLite数据库中的CRUD(创建、读取、更新和删除)操作,详细介绍了如何在Java环境中使用Person实体类进行数据库操作。文章首先阐述了SQLite数据库的基本概念及其在移动应用开发中的重要性,然后通过具体的代码示例,逐步展示了如何实现对Person实体类的增删改查功能。此外,还讨论了常见错误及其解决方法,为开发者提供了实用的参考和指导。 ... [详细]
  • HBase Java API 进阶:过滤器详解与应用实例
    本文详细探讨了HBase 1.2.6版本中Java API的高级应用,重点介绍了过滤器的使用方法和实际案例。首先,文章对几种常见的HBase过滤器进行了概述,包括列前缀过滤器(ColumnPrefixFilter)和时间戳过滤器(TimestampsFilter)。此外,还详细讲解了分页过滤器(PageFilter)的实现原理及其在大数据查询中的应用场景。通过具体的代码示例,读者可以更好地理解和掌握这些过滤器的使用技巧,从而提高数据处理的效率和灵活性。 ... [详细]
author-avatar
性感让晚安回忆流淌_507
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有