Java中的static关键字可以用于修饰变量、方法、代码块和类,还可以与import关键字联合使用,使用的方式不同赋予了static关键字不同的作用,且在开发中使用广泛,这里做一下深入了解。

静态资源(静态变量与静态方法)

被static关键字修饰的变量和方法统一属于类的静态资源,是类实例之间共享的。被static关键字修饰的变量、方法属于类变量、类方法,可以通过【类名.变量名】、【类名.方法名】直接引用,而不需要派生一个类实例出来。

静态资源分类存放的好处

JDK把不同的静态资源放在了不同的类中而不是把所有的静态资源放在一个类里面,这样做主要有3点好处:

1.不同的类有自己的静态资源,就可以实现静态资源分类。比如,和数学相关的静态资源就放在了java.lang.Math中,和日历相关的静态资源就放在java.util.Calendar中,将组织形式固定为【类>静态资源】,使得代码的逻辑结构变得清晰。

2.因为静态资源的组织形式固定为了【类>静态资源】的形式,也就有效避免的静态资源在全局重名的问题。比如在A类中有一个name属性,B类中也有一个name属性,如果放在一起会重复,但是分类放开则不会重复了,因为实际上这两个属性的全名是A.name和B.name。

3.分类有助于避免因为静态资源都放在一个类中导致该类体积过大的问题,方便了管理与协同维护。

静态资源容易混淆的三个点

静态资源的知识点比较简单,但是还是有三点比较容易混淆:静态方法能不能引用非静态资源?静态方法能不能引用静态资源?非静态方法能不能引用静态资源?要弄明白这三个问题,就要先了解静态资源在JVM中的加载机制。

实际上,虽然说静态资源是属于类的,但在JVM中却是独立于类的存在。因为从JVM类加载机制的角度来讲,静态资源是类初始化的时候加载的,而非静态资源则是派生类的时候才加载的。类的初始化早于类的派生(new)。比如,在Class.forName("xxx")方法中,就是初始化了一个类,但是并不是派生出一个实例,而只是加载了这个类中的静态资源。因此对于一个静态资源来说,它是不可能知道一个类中有哪些非静态资源的。但是对于非静态资源来说就不一样了,由于它是派生实例之后才产生的,因此属于类的这些东西它都能识别得到。至此,上面三个问题的答案已经呼之欲出了:

1.静态方法能不能引用非静态资源?答案是不能,非静态资源是派生实例之后才产生的,对于在初始化阶段就存在的静态资源来说,根本识别不到。

2.静态方法能不能引用静态资源?答案是可以,因为静态资源都是在类初始化的时候一同加载的,自然都能互相识别得到。

3.非静态方法能不能引用静态资源?答案是可以,因为非静态方法就是实例方法,在派生类实例之后产生,而静态资源已经在类初始化的时候已经存在了,自然能在引用静态资源的时候成功识别。

静态块

静态块也是static关键字的重要应用之一,作用是初始化一个类的时候做特定的操作。和静态变量、静态方法同样,静态块里面的代码只会执行一次,且只在初始化类的时候执行。静态块同样很简单,只有三个小细节要特别提及:

静态资源的加载顺序是严格按照静态资源的定义顺序来加载的。

public class A

{

private static int a = B();

static

{

System.out.println("进入A类的静态块");

}

public static void main(String[] args)

{

new A();

}

public static int B()

{

System.out.println("进入A类静态变量a.B()静态方法中");

return 1;

}

}

在这里,因为静态变量a的定义顺序在静态块之前,因此在a先被初始化的时候静态方法B先于静态块被调用执行,打印的结果是:

进入A类静态变量a.B()静态方法中

进入A类的静态块

静态代码块对于定义在它之后的静态变量,可以赋值,但是不能访问。

public class A

{

static

{

c = 3;

System.out.println(c);

}

private static int c;

}

上面这段代码会在第6行报错:Cannot reference a field before it is defined。这个特性理解起来可能比较奇怪,个人的理解是给静态方法赋值并不是实时的,Java遇到赋值语句的时候会先将这些个赋值语句缓存起来,等所有静态资源都识别完成之后再统一进行赋值。

静态代码块是严格按照父类静态代码块->子类静态代码块的顺序加载的,且只加载一次。

public class A

{

static

{

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

}

public A()

{

System.out.println("A类的构造器");

}

}

public class B extends A

{

static

{

System.out.println("B类的静态代码块");

}

public B()

{

System.out.println("B类的构造器");

}

public static void main(String[] args)

{

new B();

new B();

}

}

上面代码的结果是:

A类的静态代码块

B类的静态代码块

A类的构造器

B类的构造器

A类的构造器

B类的构造器

静态内部类

一般情况下,static是关键字是不能用于修饰类的,只有在该类是内部类的情况下才能使用static修饰,且只能修饰一个,这样的内部类被称为静态内部类(匿名内部类)。静态内部类只有在一些特殊的场景中才能用得上,比如像线程池ThreadPoolExecutor中的四种拒绝机制CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy就是静态内部类。

与import关键字联合使用

import static是JDK1.5之后的新特性,这两个关键字联合使用可以指定导入某个类中的指定静态资源,并且不需要使用类名.资源名,可以直接使用资源名。

import static java.lang.Math.*;

public class A

{

public static void main(String[] args)

{

System.out.println(sin(2.2));

}

}

这么写意味着导入了java.lang.Math包下的所有静态资源,因此在main函数里就可以直接使用sin(2,2)而不需要使用Math.sin(2,2)了。另外使用这种语法要特别注意的是,这里要写import static java.lang.Math.*,最后的【.*】不可少,有了这两个字符才意味着导入的是Math下的所有静态资源,写成import static java.lang.Math是有问题的。当然,我们也可以指定只导入某个静态资源,比如只导入Math下sin这个方法而不导入Math下的所有静态资源。

import static java.lang.Math.sin;

public class A

{

public static void main(String[] args)

{

System.out.println(sin(2.2));

}

}

使用import static这样的语法可以有效简化一些操作,比如在频繁使用Math类下静态资源的地方可以少写很多【Math.】,但是这样却降低了代码的可读性,因为这样就模糊了该静态资源的来源,弱化了分类的概念。

以上就是详解java中的static关键字的详细内容,更多关于java static关键字的资料请关注脚本之家其它相关文章!

java static 函数_详解java中的static关键字相关推荐

  1. java中static修饰函数_详解java中static关键词的作用

    在java中,static是一个修饰符,用于修饰类的成员方法.类的成员变量,另外可以编写static代码块来优化程序性能:被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载 ...

  2. java comparator相等_详解Java中Comparable和Comparator接口的区别

    详解Java中Comparable和Comparator接口的区别 发布于 2020-7-20| 复制链接 摘记: 详解Java中Comparable和Comparator接口的区别本文要来详细分析一 ...

  3. Java implement意思_详解JAVA中implement和extends的区别

    详解JAVA中implement和extends的区别 发布于 2020-4-14| 复制链接 摘记: 详解JAVA中implement和extends的区别extends是继承父类,只要那个类不是声 ...

  4. java sleep唤醒_详解Java中的线程让步yield()与线程休眠sleep()方法

    Java中的线程让步会让线程让出优先级,而休眠则会让线程进入阻塞状态等待被唤醒,这里我们对比线程等待的wait()方法,来详解Java中的线程让步yield()与线程休眠sleep()方法 线程让步: ...

  5. java runnable 异常_详解Java中多线程异常捕获Runnable的实现

    详解Java中多线程异常捕获Runnable的实现 1.背景: Java 多线程异常不向主线程抛,自己处理,外部捕获不了异常.所以要实现主线程对子线程异常的捕获. 2.工具: 实现Runnable接口 ...

  6. java 代码块_详解java中的四种代码块

    在java中用{}括起来的称为代码块,代码块可分为以下四种: 一.简介 1.普通代码块: 类中方法的方法体 2.构造代码块: 构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行. ...

  7. java 标量替换_详解jvm中的标量替换

    概述 通常在java中创建一个对象,大家都认为是在堆中创建. 在jdk6开始有逃逸分析,标量替换等技术,关于在堆中创建对象不再绝对. 关于标量替换,通过以下几点进行概述: 逃逸分析 标量替换是什么 测 ...

  8. java内部格式_详解java内部类的访问格式和规则

    详解java内部类的访问格式和规则 1.内部类的定义 定义一个类来描述事物,但是这个事物其中可能还有事物,这时候在类中再定义类来描述. 2.内部类访问规则 ①内部类可以直接访问外部类中的成员,包括私有 ...

  9. python java混合编程_详解java调用python的几种用法(看这篇就够了)

    java调用python的几种用法如下: 在java类中直接执行python语句 在java类中直接调用本地python脚本 使用Runtime.getRuntime()执行python脚本文件(推荐 ...

最新文章

  1. VC2019消息框编程总结
  2. python中def fun(a、b=200)_python中的函数的参数和可变参数
  3. mysql collect_set_hive列转行 (collect_set())
  4. 替换 centOS6.5 默认安装的旧版 firefox ,安装最新版 firefox 全过程
  5. java优化上传速度慢怎么办_网站建设中影响网站优化的一些因素
  6. Redis入门之 redis set集合的操作
  7. js系列教程8-事件全解
  8. js控制网页WMP播放的属性
  9. 变分模态分解算法matlab程序,一种基于变分模态分解理论和K最近邻算法的心电信号分类方法与流程...
  10. 测试岗(平安银行)面试总结
  11. weblogic下载安装
  12. 《代码整洁之道》第14章 逐步改进 的代码片段
  13. mysql root拿站_[转载]拿站,专业拿站,拿站工具,手工注入,手工入侵,拿站教程,拿站知识,拿站原理...
  14. FASS分布式全闪存储技术白皮书
  15. idea工作空间多开项目
  16. 极客日报:腾讯《王者荣耀》禁止未满12周岁用户充值;B站发布16款新品游戏;华为注册姚安娜商标被驳回
  17. 找不到合适的工作怎么办
  18. 人人都能成为闪电网络节点:第1章安装系统
  19. java cstring_CString 操作指南
  20. 通过分辨率区分iPhone型号(更新至13系列)

热门文章

  1. webSocket部署服务器遇到最大的坑之'Connection' header value must contain 'Upgrade' 苹果手机未能完成操作。(OSStatus错误-9801。)
  2. [图解]无光驱,无软驱,你可以这样重装系统
  3. 做新时代弄潮儿!文创产业智能化的融合与颠覆
  4. 秒传 php,文件上传之秒传文件
  5. 二分查找(python实现)
  6. Linux中启动Docker容器报错:Error response from daemon: driver failed programming external connectivity
  7. Maven项目下:@WebServlet注解失效的解决方法
  8. PSD文件不小心删除怎么恢复?PS崩溃看这里
  9. 郑州哪家公司网站建设比较好?
  10. sohu收购Go2Map案背后的3S崛起