前言

之前讲到final关键字的作用是每次面试的时候我必问求职者的两个问题之一,另外一个问题就是文本会写到的static。final和static一样,都是一个小问题可以看到一个人的基础是否扎实以及平时是否有钻研精神。

静态变量和静态方法

static关键字最基本的用法是:

1、被static修饰的变量属于类变量,可以通过类名.变量名直接引用,而不需要new出一个类来

2、被static修饰的方法属于类方法,可以通过类名.方法名直接引用,而不需要new出一个类来

被static修饰的变量、被static修饰的方法统一属于类的静态资源,是类实例之间共享的,换言之,一处变、处处变。JDK把不同的静态资源放在了不同的类中而不把所有静态资源放在一个类里面,很多人可能想当然认为当然要这么做,但是是否想过为什么要这么做呢?个人认为主要有三个好处:

1、不同的类有自己的静态资源,这可以实现静态资源分类。比如和数学相关的静态资源放在java.lang.Math中,和日历相关的静态资源放在java.util.Calendar中,这样就很清晰了

2、避免重名。不同的类之间有重名的静态变量名、静态方法名也是很正常的,如果所有的都放在一起不可避免的一个问题就是名字重复,这时候怎么办?分类放置就好了。

3、避免静态资源类无限膨胀,这很好理解。

OK,再微微深入一下,也是有些人容易混淆的一个问题:静态方法能不能引用非静态资源?静态方法里面能不能引用静态资源?非静态方法里面能不能引用静态资源?比如就以这段代码为例,是否有错?

1 public class A2 {3 private int i = 1;4 5 public static void main(String[] args)6 {7 i = 1;8 }9 }

当然有错,在第7行的地方。不妨这么思考这个问题:

静态资源属于类,但是是独立于类存在的。从JVM的类加载机制的角度讲,静态资源是类初始化的时候加载的,而非静态资源是类new的时候加载的。类的初始化早于类的new,比如Class.forName(“xxx”)方法,就是初始化了一个类,但是并没有new它,只是加载这个类的静态资源罢了。所以对于静态资源来说,它是不可能知道一个类中有哪些非静态资源的;但是对于非静态资源来说就不一样了,由于它是new出来之后产生的,因此属于类的这些东西它都能认识。所以上面的几个问题答案就很明确了:

1、静态方法能不能引用非静态资源?不能,new的时候才会产生的东西,对于初始化后就存在的静态资源来说,根本不认识它。

2、静态方法里面能不能引用静态资源?可以,因为都是类初始化的时候加载的,大家相互都认识。

3、非静态方法里面能不能引用静态资源?可以,非静态方法就是实例方法,那是new之后才产生的,那么属于类的内容它都认识。

静态块

静态块也是static的重要应用之一。也是用于初始化一个类的时候做操作用的,和静态变量、静态方法一样,静态块里面的代码只执行一次,且只在初始化类的时候执行。静态块很简单,不过提三个小细节:

 1 public class A 2 { 3 private static int a = B(); 4  5 static 6 { 7 System.out.println("Enter A.static block"); 8 } 9 10 public static void main(String[] args)11 {12 new A();13 }14 15 public static int B()16 {17 System.out.println("Enter A.B()");18 return 1;19 }20 }

打印结果是:

Enter A.B()Enter A.static block

得出第一个结论:静态资源的加载顺序是严格按照静态资源的定义顺序来加载的。这和周志明老师《深入理解Java虚拟机:JVM高级特性与最佳实践》中类初始化中的说法“()方法是由编译器自动收集类中所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的”是一致的。

再看一个例子:

 1 public class A 2 { 3 static 4 { 5 c = 3; 6 System.out.println(c); 7 } 8  9 private static int c;10 }

这段代码的第6行是有错误的“Cannot reference a field before it is defined”。从这个例子得出第二个结论:静态代码块对于定义在它之后的静态变量,可以赋值,但是不能访问

最后一个小例子:

 1 public class A 2 { 3 static 4 { 5 System.out.println("A.static block"); 6 } 7  8 public A() 9 {10 System.out.println("A.constructor()");11 }12 } 1 public class B extends A 2 { 3 static  4 { 5 System.out.println("B.static block"); 6 } 7  8 public B() 9 {10 System.out.println("B.constructor()");11 }12 13 public static void main(String[] args)14 {15 new B();16 new B();17 }18 }

结果是

A.static blockB.static blockA.constructor()B.constructor()A.constructor()B.constructor()

这个例子得出第三个结论:静态代码块是严格按照父类静态代码块->子类静态代码块的顺序加载的,且只加载一次

static修饰类

这个用得相对比前面的用法少多了,static一般情况下来说是不可以修饰类的,如果static要修饰一个类,说明这个类是一个静态内部类(注意static只能修饰一个内部类),也就是匿名内部类。像线程池ThreadPoolExecutor中的四种拒绝机制CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy就是静态内部类。静态内部类相关内容会在写内部类的时候专门讲到。

import static

这个比较冷门,基本很少看见有地方用,使用JUnit可能会用到,写assert的时候会方便些。import static是JDK1.5之后的新特性,这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名.资源名,可以直接使用资源名。注意一下,import static必须这么写,而不能写成static import。举个例子来看一下:

1 import static java.lang.Math.*;2 3 public class A4 {5 public static void main(String[] args)6 {7 System.out.println(sin(2.2));8 }9 }

这么写意味着我导入了Math下的所有静态资源,main函数里面我就可以直接用sin(2.2)而不需要使用Math.sin(2.2)了。注意一下,要写import static java.lang.Math.*,最后的“.*”不可少,有了这两个字符才意味着导入的是Math下的所有静态资源,写成import static java.lang.Math是有问题的。当然,我们也可以指定只导入某个静态资源,比如只导入Math下sin这个方法而不导入Math下的所有静态资源:

1 import static java.lang.Math.sin;2 3 public class A4 {5 public static void main(String[] args)6 {7 System.out.println(sin(2.2));8 }9 }

这么写也是没问题的。导入静态变量也是一样,有兴趣的可以自己试一下。对于import static,个人的态度是:

1、简化了一些操作,比如静态导入Math下的所有静态资源,在频繁使用Math类下静态资源的地方,可以少些很多“Math.”

2、降低了代码的可读性

建议在某些场景下导入特定的静态资源,不建议使用“.*”的导入方式。

======================================================

新春佳节,小编在这祝大家:喜迎猪年,愿君身体健康,福寿绵长,吉祥如意,财源滚滚,心想事成,万事顺利,新年快乐,好运平安!

java static关键字_Java基础:static关键字作用总结相关推荐

  1. java static用法_Java中static关键字的作用和用法详细介绍

    static表示"全局"或者"静态"的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static ...

  2. java static是单例_JAVA基础-static关键字及单例设计模式

    static关键字 基本概念使用static关键字修饰成员变量表示静态的含义, 此时成员变量由对象层级提升为类层级, 也就是整个类只有一份并被所有对象共享. 该成员变量随着类的加载准备就绪, 与是否创 ...

  3. java static final关键字_Java的static与final关键字

    版权声明:转载原创文章请以超链接形式请注明原文章出处,尊重作者,尊重原创! 恰饭广告 static:(静态修饰符)面向对象中static修饰的内容是隶属于类,而不是直接隶属于对象的,所以static修 ...

  4. java outer关键字_java中的关键字

    abstract : 表明类或者成员方法具有抽象属性 assert : 断言,用来进行程序调试 boolean :基本数据类型之一,声明布尔类型的关键字 break :提前跳出一个块 byte :基本 ...

  5. java中关键字_java中的关键字是什么?

    展开全部 访问控制: private 私有的 protected 受保护的 public 公共的 类.方法和变量修饰符 abstract 声明抽象 class 类 extends 扩允,继承 fina ...

  6. java 有哪些关键字_JAVA的常用关键字有哪些?

    JAVA的常用关键字有哪些? 发布时间:2020-05-25 21:46:00 来源:亿速云 阅读:133 作者:鸽子 下表是java中经常会用到的关键字: 一:用于定义访问权限修饰符的关键字: 1) ...

  7. java super用法_Java基础面试题汇总

    blog.csdn.net/ThinkWon/article/details/104390612 Java概述 何为编程 编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结 ...

  8. 先有java后有天_Java基础第十四天总结——面向对象(下)

    一.关键字:static 二.理解main方法的语法 三.类的成员之四:代码块 四.关键字:final /*-------------------分割线------------------*/ 一.关 ...

  9. java 多线程 总结_java基础总结大全(三)多线程

    三.多线程: 1.进程和线程: 进程:正在进行的程序.每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元. 线程:进程内部的一条执行路径或者一个控制单元. 两者的区别: 一个进程 ...

最新文章

  1. 为什么《七周七语言》选中的是这几种语言?
  2. Sqlserver中一直在用又经常被忽略的知识点一
  3. 【Python-ML】SKlearn库决策树(DecisionRegression) 使用
  4. Django使用心得(二)
  5. 【UVA 437】The Tower of Babylon(记忆化搜索写法)
  6. java string转decimal_java中string转bigdecimal的例子
  7. linux定时任务清理cache缓存
  8. LeetCode 1856. 子数组最小乘积的最大值(前缀和 + 单调栈)
  9. nodejs 安装express
  10. String源码分析,中高级Java开发面试题
  11. python数组写入txt
  12. 65 ----点到平面及直线的距离、两异面直线间的距离
  13. mysql2008无法启动_SQL Sever2008r2 数据库服务各种无法启动的解决办法
  14. 面经 - 计算机网络知识点
  15. 北科大计算机学院何杰,北京科技大学计算机科学与技术系硕士生导师何杰_计算机考研导师...
  16. 利用第三方软件识别图片文字并转换为文本
  17. 20201002Class not found XXXXTest
  18. 快速注册认证小程序,三分钟学会免300元认证企业小程序
  19. 滑膜间充质干细胞复合壳聚糖水凝胶/角蛋白壳聚糖水凝胶复合材料/壳聚糖/海藻酸纳复合水凝胶的制备
  20. kali linux 初始密码

热门文章

  1. 前台传JSON到后台
  2. Unix中$$、$@、$#、$*的意思
  3. poj 1260 动态规划
  4. Linq在sharepoint中的查询
  5. 《程序设计技术》课程辅助学习资料
  6. 使用 matlab 数据集的生成(generate datasets)
  7. 可变对象 vs 不可变对象(Python)
  8. Linux 下 ascii 的查看方式
  9. 放缩法 —— 渐进记号的相关证明
  10. 机器学习基础(四十)—— 将距离转换为权重