热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

static关键字有什么作用

static是Java50个关键字之一。static关键字可以用来修饰代码块表示静态代码块,修饰成员变量表示全局静态成员变量,修饰方法表示静态方法。
今天主要学习下Java语言中的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;
}

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

注意:

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

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关键字修饰普通类。

4 静态导入

在用import导入包或者类时,可以用static修饰包名或者类,表示静态导入。静态导入可以与动态导入放在一起比较来加深理解。

动态导入是当你程序运行时需要new一个不在此包中的类的对象时,才会根据全路径类名加载类;而静态导入则是随着类的加载而加载静态导入的类,所以它是提前导入的。

public class StaticTest {
	static void method1() {
		System.out.println("static method1");
	}
	
	static void method2() {
		System.out.println("static method2");
	}
}

静态导入:

import static com.starry.staticImport.StaticTest.method1;

public class Client {
	public static void main(String[] args) {
		method1();   // 
		StaticTest.method2();
	}
}

注意method1()是静态导入,所以可以不需要通过类名访问;而method2()没有导入,则需要通过类名调用。那么什么时候需要静态导入呢?

静态导入常用于静态方法以及含有静态方法的类,枚举类等的导入,可以在编译阶段确定导入类的信息或者方法信息。

static关键字的缺点

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

以上就是static关键字有什么作用的详细内容,更多请关注其它相关文章!


推荐阅读
  • 优化联通光猫DNS服务器设置
    本文详细介绍了如何为联通光猫配置DNS服务器地址,以提高网络解析效率和访问体验。通过智能线路解析功能,域名解析可以根据访问者的IP来源和类型进行差异化处理,从而实现更优的网络性能。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 如何配置Unturned服务器及其消息设置
    本文详细介绍了Unturned服务器的配置方法和消息设置技巧,帮助用户了解并优化服务器管理。同时,提供了关于云服务资源操作记录、远程登录设置以及文件传输的相关补充信息。 ... [详细]
  • 网络攻防实战:从HTTP到HTTPS的演变
    本文通过一系列日记记录了从发现漏洞到逐步加强安全措施的过程,探讨了如何应对网络攻击并最终实现全面的安全防护。 ... [详细]
  • 本文介绍了如何在 DB2 环境中创建和删除数据库编目。创建编目是连接新数据库的必要步骤,涉及获取数据库连接信息、使用命令行工具进行配置,并验证连接的有效性。删除编目则用于移除不再需要的数据库连接。 ... [详细]
  • CentOS 7 磁盘与文件系统管理指南
    本文详细介绍了磁盘的基本结构、接口类型、分区管理以及文件系统格式化等内容,并提供了实际操作步骤,帮助读者更好地理解和掌握 CentOS 7 中的磁盘与文件系统管理。 ... [详细]
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 探讨如何通过编程技术实现100个并发连接,解决线程创建顺序问题,并提供高效的并发测试方案。 ... [详细]
  • 本周信息安全小组主要进行了CTF竞赛相关技能的学习,包括HTML和CSS的基础知识、逆向工程的初步探索以及整数溢出漏洞的学习。此外,还掌握了Linux命令行操作及互联网工作原理的基本概念。 ... [详细]
  • 本文详细介绍了如何使用PHP检测AJAX请求,通过分析预定义服务器变量来判断请求是否来自XMLHttpRequest。此方法简单实用,适用于各种Web开发场景。 ... [详细]
  • 本文介绍了如何在具备多个IP地址的FTP服务器环境中,通过动态地址端口复用和地址转换技术优化网络配置。重点讨论了2Mb/s DDN专线连接、Cisco 2611路由器及内部网络地址规划。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 邮件(带附件,模拟文件上传,跨服务器)发送核心代码1.测试邮件发送附件接口***测试邮件发送附件*@parammultipartFile*@return*@RequestMappi ... [详细]
author-avatar
手机用户2502903937
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有