今天主要学习下Java语言中的static关键字。

static关键字的含义及使用场景

static是Java50个关键字之一。static关键字可以用来修饰代码块表示静态代码块,修饰成员变量表示全局静态成员变量,修饰方法表示静态方法。(注意:不能修饰普通类,除了内部类,这是为什么?)

class A {

static {

System.out.println("A : 静态代码块");

}

static int i ; // 静态变量

static void method() {

System.out.println("A: 静态方法");

}

}

简而言之,被static关键字修饰的内容都是静态的。

静态是相对于动态的,动态是指Java程序在JVM上运行时,JVM会根据程序的需要动态创建对象并存储对象(分配内存),对象使命结束后,对象会被垃圾回收器销毁,即内存回收由JVM统一管理并分配给其他新创建的对象;静态是指Java程序还没有运行时,JVM就会为加载的类分配空间存储被static关键字修饰的内容;如静态成员变量,Java类加载到JVM中,JVM会把类以及类的静态成员变量存储在方法区,我们知道方法区是线程共享且很少发生GC的区域,所以被static关键字修饰的内容都是全局共享的,且只会为其分配一次存储空间。

所以当类的某些内容不属于对象,而由对象共享即属于类的时候,就可以考虑是否用static关键字进行修饰。

static关键字的的作用

1 修饰代码块

类中用static关键字修饰的代码块称为静态代码,反之没有用static关键字修饰的代码块称为实例代码块。

实例代码块会随着对象的创建而执行,即每个对象都会有自己的实例代码块,表现出来就是实例代码块的运行结果会影响当前对象的内容,并随着对象的销毁而消失(内存回收);而静态代码块是当Java类加载到JVM内存中而执行的代码块,由于类的加载在JVM运行期间只会发生一次,所以静态代码块也只会执行一次。

因为静态代码块的主要作用是用来进行一些复杂的初始化工作,所以静态代码块跟随类存储在方法区的表现形式是静态代码块执行的结果存储在方法区,即初始化量存储在方法区并被线程共享。

2 修饰成员变量

类中用static关键字修饰的成员变量称为静态成员变量,因为static不能修饰局部变量(为什么?),因此静态成员变量也能称为静态变量。静态变量跟代码块类似,在类加载到JVM内存中,JVM会把静态变量放入方法区并分配内存,也由线程共享。访问形式是:类名.静态成员名。

public class StaticTest {

public static void main(String[] args) {

System.out.println(D.i);

System.out.println(new D().i);

}

}

class D {

static {

i = 2;

System.out.println("D : 静态代码块1");

}

static int i;

}

运行结果:

D : 静态代码块1

2

2

静态变量存储在类的信息中,且可以在线程间共享,那么它当然也属于该类的每个对象,因此可以通过对象访问静态变量,但编译器并不支持这么做,且会给出警告。

注意:

一个类的静态变量和该类的静态代码块的加载顺序。类会优先加载静态变量,然后加载静态代码块,但有多个静态变量和多个代码块时,会按照编写的顺序进行加载。

class D {

static {

i = 2;

System.out.println("D : 静态代码块1");

}

static {

i = 6;

System.out.println("D : 静态代码块2");

}

static int i;

}

可以想一下运行的结果。

静态变量可以不用显式的初始化,JVM会默认给其相应的默认值。如基本数据类型的byte为0,short为0,char为\u0000,int为0,long为0L,float为0.0f,double为0.0d,boolean为false,引用类型统一为null。

静态变量既然是JVM内存中共享的且可以改变,那么对它的访问会引起线程安全问题(线程A改写的同时,线程B获取它的值,那么获取的是修改前的值还是修改后的值呢?),所以使用静态变量的同时要考虑多线程情况。如果能确保静态变量不可变,那么可以用final关键字一起使用避免线程安全问题;否则需要采用同步的方式避免线程安全问题,如与volatile关键字一起使用等。

static关键不能修饰局部变量,包括实例方法和静态方法,不然就会与static关键字的初衷-共享相违背。

3 修饰方法

用static关键字修饰的方法称为静态方法,否则称为实例方法。通过类名.方法名调用,但需要注意静态方法可以直接调用类的静态变量和其他静态方法,不能直接调用成员变量和实例方法(除非通过对象调用)。

class D {

static {

i = 2;

System.out.println("D : 静态代码块");

}

static final int i;

int j;

static void method() {

System.out.println(i);

System.out.println(new D().j);

method1();

new D().method2();

}

static void method1() {

System.out.println(i);

}

void method2() {

System.out.println(i);

}

}

注意:既然类的实例方法需要对象调用才能访问,而静态方法直接通过类名就能访问,那么在不考虑部署服务器的情况下,一个类是如何开始执行的呢?最大的可能就是通过“类名.静态方法”启动Java,而我定义那么多静态方法,JVM又是如何知道主入口呢?

或许,你想到了main方法。

没错,就是main方法被Java规范定义成Java类的主入口。Java类的运行都由main方法开启:

public static void main(String[] args) {

for (String arg : args) { // 参数由外部定义System.out.println(arg);

}

}

但注意main并不是Java关键字,它只是一个规定的程序入口的方法名字;另外main方法可以重载。

注意:static关键字虽然不能修饰普通类,但可以用static关键字修饰内部类使其变成静态内部类。static关键字本身的含义就是共享,而Java类加载到JVM内存的方法区,也是线程共享的,所以没必要用static关键字修饰普通类。

static关键字的缺点

封装是Java类的三大特性之一,也是面向对象的主要特性。因为不需要通过对象,而直接通过类就能访问类的属性和方法,这有点破坏类的封装性;所以除了Utils类,代码中应该尽量少用static关键字修饰变量和方法。

作者:Starry-

来源:CSDN

java中static关键字的作用_面试|static 关键字有什么作用相关推荐

  1. java中的分页 效率考虑_面试官:数据量很大,分页查询很慢,有什么优化方案?...

    当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询.对于数据库分页查询,也有很多种方法和优化的点. 下面简单说一下我知道的一些 ...

  2. java中修饰常量的事_浅谈java中的声明常量为什么要用static修饰

    今天定义一个类常量,想着也只有这个类可以用到,就没用static关键字修饰.结果sonar代码检查提示: Rename this field "PERSON_TYPE_USER" ...

  3. 转:Java中子类是否可以继承父类的static变量和方法而呈现多态特性

    原文地址:Java中子类是否可以继承父类的static变量和方法而呈现多态特性 静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明 ...

  4. java中线程死锁及避免_如何避免Java线程中的死锁?

    java中线程死锁及避免 如何避免Java中的死锁? 是Java面试中最受欢迎的问题之一,也是本季多线程的风格,主要是在高层提出,并带有很多后续问题. 尽管问题看起来很基础,但是一旦您开始深入研究,大 ...

  5. java腾讯字符串面试题_面试百度、阿里、腾讯,这134道Java面试题你会多少?

    这里一共是134道Java面试题,看看你能对几道吧! 1. Java 语言有哪些特点 2. 面向对象和面向过程的区别 3. 关于 JVM JDK 和 JRE 最详细通俗的解答 4. Oracle JD ...

  6. 39.在Java中定义一个不做事且没有参数的构造方法的作用?

    1 在Java中定义一个不做事且没有参数的构造方法的作用 Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会 调用父类中"没有参数的构造方法&quo ...

  7. java中final是啥意思_(转)深入理解Java中的final关键字

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  8. 简述java中的注释以及用法_怎样理解 Java 注解和运用注解编程?

    正好最近在公众号(BetterAndroid)发了一篇关于注解的文章,贴在这里吧,希望对题主有帮助. 一.什么是注解 我们都知道在Java代码中使用注释是为了提升代码的可读性,也就是说,注释是给人看的 ...

  9. java多线程写在哪一层_面试知识点三:Java多线程

    35.并行和并发有什么区别? 36.线程和进程的区别? 37.守护线程是什么? 38.创建线程有哪几种方式? 39.说一下 runnable 和 callable 有什么区别? 40.线程有哪些状态? ...

最新文章

  1. R语言绘图-常用参数
  2. MATLAB应用实战系列NSGA-II多目标优化算法原理及应用实例(附MATLAB代码)
  3. 【JavaSE04】Java中循环语句for,while,do···while-练习2
  4. dubbo负载均衡策略配置
  5. (100)FPGA单沿和双沿采样(下降沿采样)
  6. 样条线怎么挤出平面_最速降线的故事
  7. VTK(0)---CMake工程
  8. cmos逻辑门传输延迟时间_电路基础:详解TTL和CMOS电平
  9. onselectstart和onselect的使用
  10. 数据结构实习(欢迎大家一起在评论区交流学习)
  11. linux系统下配置无线网卡的方法,linux系统下配置无线网卡的具体步骤
  12. 海通股票交易接口查询当日成交c++源码分享
  13. 初来乍到,捣鼓捣鼓前端
  14. 传教士与野人过河问题 人工智能实验算法
  15. [Swift]LeetCode1108. IP 地址无效化 | Defanging an IP Address
  16. 蔡氏混沌matlab,蔡氏混沌电路的MATLAB仿真研究_高见芳
  17. 【AcWing周赛】AcWing第86场周赛
  18. 2018年外链发布平台
  19. 安装升级最新版本postman时遇到“无法定位程序输入点 SetDefaultDllDirectories于动态链接库KERNEL32.dll 上.”的问题
  20. Dw2021下载安装教程

热门文章

  1. 计算机使用个人经验及日常维护
  2. Node解析二进制文件
  3. 加入腾讯云自媒体分享计划,拿云+社区定制周边礼包
  4. Thinkpad E440 屏幕自动调节,进BIOS设置Display,把显卡改为集成的那个。
  5. electron系统托盘与右键菜单
  6. mipush的receiver无法获得消息,断点也失效,原因很奇葩strings.xml缺少内容
  7. MIT 18.06 Gilbert Strang《线性代数》L3. 乘法和逆矩阵
  8. uniapp+高德地图api 获取定位信息及详细地址
  9. XX项目测试策略思维导图
  10. 如何搭建个人云盘?(支持WebDav):Cloudreve+阿里云+宝塔面板(详细教程)