Java基础:static关键字作用总结 static关键字详解
yuyutoo 2024-10-12 00:56 6 浏览 0 评论
前言
之前讲到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 A 2 { 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高级特性与最佳实践》中类初始化中的说法“<clinit>()方法是由编译器自动收集类中所有类变量的赋值动作和静态语句块(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 block B.static block A.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 A 4 { 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 A 4 { 5 public static void main(String[] args) 6 { 7 System.out.println(sin(2.2)); 8 } 9 }
这么写也是没问题的。导入静态变量也是一样,有兴趣的可以自己试一下。对于import static,个人的态度是:
1、简化了一些操作,比如静态导入Math下的所有静态资源,在频繁使用Math类下静态资源的地方,可以少些很多“Math.”
2、降低了代码的可读性
建议在某些场景下导入特定的静态资源,不建议使用“.*”的导入方式。
======================================================
新春佳节,小编在这祝大家:喜迎猪年,愿君身体健康,福寿绵长,吉祥如意,财源滚滚,心想事成,万事顺利,新年快乐,好运平安!
相关推荐
- 深度解读Spring框架的核心原理
-
深度解读Spring框架的核心原理在Java开发的世界里,提到Spring框架,就像提起一位久经沙场的老将,它几乎成了企业级应用开发的代名词。那么,这个被无数开发者膜拜的框架究竟有何独特之处?今天,我...
- 「Spring认证」Spring 框架概述
-
Spring是最流行的企业Java应用程序开发框架。全球数以百万计的开发人员使用SpringFramework来创建高性能、易于测试和可重用的代码。Spring框架是一个开源的Java...
- 学习Spring框架 这一篇就够了
-
1.spring概述1.1Spring是什么(理解)...
- Spring框架双核解析:IOC与AOP的本质与实战
-
#Spring核心#IOC容器#AOP编程#Java框架设计...
- Spring Boot与传统Spring框架的对比:探索Java开发的新境界
-
SpringBoot与传统Spring框架的对比:探索Java开发的新境界在Java生态系统中,Spring框架无疑是一个里程碑式的存在。从最初的简单依赖注入容器,到如今覆盖企业级开发方方面面的庞大...
- Spring MVC框架源码深度剖析:从入门到精通
-
SpringMVC框架源码深度剖析:从入门到精通SpringMVC框架简介SpringMVC作为Spring框架的一部分,为构建Web应用程序提供了强大且灵活的支持。它遵循MVC(Model-V...
- Spring框架入门
-
一.spring是什么?Spring是分层...
- 程序员必知必会技能之Spring框架基础——面向切面编程!
-
面向切面编程AOP(AspectOrientedProgramming)与OOP(ObjectOrientedProgramming,面向对象编程)相辅相成。AOP提供了与OOP不同的抽象软件结...
- Spring Security安全框架深度解读:为你的应用穿上“钢铁铠甲”
-
SpringSecurity安全框架深度解读:为你的应用穿上“钢铁铠甲”在现代网络世界里,保护我们的应用程序免受各种威胁攻击至关重要。而在这个过程中,SpringSecurity框架无疑是我们最可...
- Spring框架的设计哲学与实现:打造轻量级的企业级Java应用
-
Spring框架的设计哲学与实现:打造轻量级的企业级Java应用Spring框架自2003年诞生以来,已成为企业级Java应用开发的代名词。它不仅仅是一个框架,更是一种设计理念和哲学的体现。本文将带你...
- Spring框架深度解析:从核心原理到底层实现的全方位避坑指南
-
一、Spring框架核心概念解析1.控制反转(IoC)与依赖注入(DI)Spring的核心思想是通过IoC容器管理对象的生命周期和依赖关系。传统开发中,对象通过new主动创建依赖对象,导致高耦合;而S...
- Java框架 —— Spring简介
-
简介一般来说,Spring指的是SpringFramework,它提供了很多功能,例如:控制反转(IOC)、依赖注入...
- Spring 框架概述,模块划分
-
Spring框架以控制反转(InversionofControl,IoC)和面向切面编程(Aspect-OrientedProgramming,AOP)为核心,旨在简化企业级应用开发,使开发者...
- spring框架怎么实现依赖注入?
-
依赖注入的作用就是在使用Spring框架创建对象时,动态的将其所依赖的对象注入到Bean组件中,其实现方式通常有两种,一种是属性setter方法注入,另一种是构造方法注入。具体介绍如下:●属性set...
- Spring框架详解
-
Spring是一种开放源码框架,旨在解决企业应用程序开发的复杂性。一个主要优点就是它的分层体系结构,层次结构让你可以选择要用的组件,同时也为J2EE应用程序开发提供了集成框架。 Spring特征...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
推荐7个模板代码和其他游戏源码下载的网址
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)