热门标签 | 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开发中,保护代码安全是一个重要的课题。由于Java字节码容易被反编译,因此使用代码混淆工具如ProGuard变得尤为重要。本文将详细介绍如何使用ProGuard进行代码混淆,以及其基本原理和常见问题。 ... [详细]
  • 本文详细介绍了 `org.apache.tinkerpop.gremlin.structure.VertexProperty` 类中的 `key()` 方法,并提供了多个实际应用的代码示例。通过这些示例,读者可以更好地理解该方法在图数据库操作中的具体用途。 ... [详细]
  • Beetl是一款先进的Java模板引擎,以其丰富的功能、直观的语法、卓越的性能和易于维护的特点著称。它不仅适用于高响应需求的大型网站,也适合功能复杂的CMS管理系统,提供了一种全新的模板开发体验。 ... [详细]
  • 深入解析Java中的空指针异常及其预防策略
    空指针异常(NullPointerException,简称NPE)是Java编程中最常见的异常之一。尽管其成因显而易见,但开发人员往往容易忽视或未能及时采取措施。本文将详细介绍如何有效避免空指针异常,帮助开发者提升代码质量。 ... [详细]
  • 问题场景用Java进行web开发过程当中,当遇到很多很多个字段的实体时,最苦恼的莫过于编辑字段的查看和修改界面,发现2个页面存在很多重复信息,能不能写一遍?有没有轮子用都不如自己造。解决方式笔者根据自 ... [详细]
  • spring boot使用jetty无法启动 ... [详细]
  • importjava.io.*;importjava.util.*;publicclass五子棋游戏{staticintm1;staticintn1;staticfinalintS ... [详细]
  • 深入理解Java SE 8新特性:Lambda表达式与函数式编程
    本文作为‘Java SE 8新特性概览’系列的一部分,将详细探讨Lambda表达式。通过多种示例,我们将展示Lambda表达式的不同应用场景,并解释编译器如何处理这些表达式。 ... [详细]
  • JUC并发编程——线程的基本方法使用
    目录一、线程名称设置和获取二、线程的sleep()三、线程的interrupt四、join()五、yield()六、wait(),notify(),notifyAll( ... [详细]
  • IO流——字符流 BufferedReader / BufferedWriter 进行文件读写
    目录节点流、处理流读文件:BufferedReader的使用写文件:BufferedWriter的使用节点流处理流节点流和处理流的区别和联系字符流Buf ... [详细]
  • Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ... [详细]
  • Java 初次编程练习
    任务要求:设计一个类,包含若干基本属性和至少两个方法(可以从日常生活场景中提取)。在类中实现两个具有不同参数的构造方法。另外,设计一个包含 main 方法的类,用于测试和应用上述类。此作业需编写并调试通过。 ... [详细]
  • java解析json转Map前段时间在做json报文处理的时候,写了一个针对不同格式json转map的处理工具方法,总结记录如下:1、单节点单层级、单节点多层级json转mapim ... [详细]
  • 可参照github代码:https:github.comrabbitmqrabbitmq-tutorialsblobmasterjavaEmitLogTopic.ja ... [详细]
  • 管理UINavigationController中的手势返回 - Managing Swipe Back Gestures in UINavigationController
    本文介绍了如何在一个简单的闪存卡片应用中实现平滑的手势返回功能,以增强用户体验。 ... [详细]
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社区 版权所有