Java中static关键字的定义

1、static存在的主要意义

static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!

static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

2、static的独特之处

1、被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。

怎么理解 “被类的实例对象所共享” 这句话呢?就是说,一个类的静态成员,它是属于大伙的【大伙指的是这个类的多个对象实例,我们都知道一个类可以创建多个实例!】,所有的类对象共享的,不像成员变量是自个的【自个指的是这个类的单个实例对象】…我觉得我已经讲的很通俗了,你明白了咩?

2、在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。

3、static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!

4、被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。

3、static应用场景

因为static是被类的实例对象所共享,因此如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量。

因此比较常见的static应用场景有:

1、修饰成员变量

2、修饰成员方法

3、静态代码块

4、修饰类【只能修饰内部类也就是静态内部类】

5、静态导包

以上的应用场景将会在下文陆续讲到…

4、静态变量和实例变量的概念

静态变量:

static修饰的成员变量叫做静态变量【也叫做类变量】,静态变量是属于这个类,而不是属于是对象。

实例变量:

没有被static修饰的成员变量叫做实例变量,实例变量是属于这个类的实例对象。

还有一点需要注意的是:static是不允许用来修饰局部变量,不要问我问什么,因为java规定的!

5、静态变量和实例变量区别【重点常用】

静态变量:

静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。

实例变量:

每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。

怎么理解呢?打个比喻吧…就比方说程序员小王是一个比较温柔阳光的男孩子,这1024的这一天,老板闲的没事,非要拉着程序员小王来玩耍,怎么个玩法呢?老板和小王一人拿着一把菜刀,规则很简单,互相伤害,一人一刀,你一刀,我一刀…游戏一开始,老板二话不说,跳起来就是一刀,程序员小王二话也没说反手就是一菜刀回去,这个时候老板发飙了,双眼瞪得忒大,跳起来又是一刀,这个时候程序员小王不敢还手了,就没动手。没想到老板越来越生猛,左一刀右一刀全程下来差不多砍个半个时…程序员小王一直没有还过手,因为小王知道他是老板…

这个程序员小王只会在老板第一次挥刀的时候,回老板一刀,之后就不还手了,这个时候我们把程序员小王看做是静态变量,把老板第一次向小王挥刀看做是类加载,把小王回老板一刀看出是分配内存空间,而一人一刀这个回合过程看成是类加载的过程,之后老板的每一刀都看成是创建一次对象。

连贯起来就是static变量值在类第一次加载的时候分配空间,以后创建类对象的时候不会重新分配

之后这个老板挨了一刀之后躺医院了一年,一出院回到公司第一件事就是拉程序员宜春出来玩耍,老板殊不知其然,这个博主程序员宜春性格异常暴躁,老板递给程序员宜春一把菜刀,博主宜春一接过菜刀,猝不及防的被老板跳起来就是一刀,程序员宜春痛的嗷了一声,暴躁的程序员宜春还没嗷完,在嗷的同时跳起来就是给老板一刀,接着老板跳起来又是一刀,程序员宜春嗷的一声又是回一刀,老板跳起来又一刀,程序员宜春嗷的一声又是回一刀,只要老板没停程序员宜春就没停,因为程序员宜春知道,就自己这曝脾气,暴躁起来si都敢摸,肯定有几个老铁知道…

程序员宜春就类似实例变量,每次创建对象,都会为每个对象分配成员变量内存空间,就像老板来一刀,程序员宜春都会回一刀这样子的…

6、访问静态变量和实例变量的两种方式

我们都知道静态变量是属于这个类,而不是属于是对象,static独立于对象。

但是各位有木有想过:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问【只要访问权限足够允许就行】,不理解没关系,来个代码就理解了

public class StaticDemo {

static int value = 666;

public static void main(String[] args) throws Exception{

new StaticDemo().method();

}

private void method(){

int value = 123;

System.out.println(this.value);

}

}

猜想一下结果,我猜你的结果是123,哈哈是咩?其实

运行结果: 666

1

回过头再去品味一下上面的那段话,你就能非常客观明了了,这个思想概念要有只是这种用法不推荐!

因此小结一下访问静态变量和实例变量的两种方法:

静态变量:

类名.静态变量

对象.静态变量(不推荐)

静态方法:

类名.静态方法

对象.静态方法(不推荐)

7、static静态方法

static修饰的方法也叫做静态方法,不知道各位发现咩有,其实我们最熟悉的static静态方法就是main方法了小白童鞋:喔好像真的是哦。由于对于静态方法来说是不属于任何实例对象的,this指的是当前对象,因为static静态方法不属于任何对象,所以就谈不上this了。

还有一点就是:构造方法不是静态方法!

8、static静态代码块

先看个程序吧,看看自个是否掌握了static代码块,下面程序代码继承关系为 BaseThree——> BaseTwo——> BaseOne

BaseOne类

package com.gx.initializationblock;

public class BaseOne {

public BaseOne() {

System.out.println("BaseOne构造器");

}

{

System.out.println("BaseOne初始化块");

System.out.println();

}

static {

System.out.println("BaseOne静态初始化块");

}

}

BaseTwo类

package com.gx.initializationblock;

public class BaseTwo extends BaseOne {

public BaseTwo() {

System.out.println("BaseTwo构造器");

}

{

System.out.println("BaseTwo初始化块");

}

static {

System.out.println("BaseTwo静态初始化块");

}

}

BaseThree 类

package com.gx.initializationblock;

public class BaseThree extends BaseTwo {

public BaseThree() {

System.out.println("BaseThree构造器");

}

{

System.out.println("BaseThree初始化块");

}

static {

System.out.println("BaseThree静态初始化块");

}

}

测试demo2类

package com.gx.initializationblock;

/*

注:这里的ABC对应BaseOne、BaseTwo、BaseThree

* 多个类的继承中初始化块、静态初始化块、构造器的执行顺序

在继承中,先后执行父类A的静态块,父类B的静态块,最后子类的静态块,

然后再执行父类A的非静态块和构造器,然后是B类的非静态块和构造器,最后执行子类的非静态块和构造器

*/

public class Demo2 {

public static void main(String[] args) {

BaseThree baseThree = new BaseThree();

System.out.println("-----");

BaseThree baseThree2 = new BaseThree();

}

}

运行结果

BaseOne静态初始化块

BaseTwo静态初始化块

BaseThree静态初始化块

BaseOne初始化块

BaseOne构造器

BaseTwo初始化块

BaseTwo构造器

BaseThree初始化块

BaseThree构造器

-----

BaseOne初始化块

BaseOne构造器

BaseTwo初始化块

BaseTwo构造器

BaseThree初始化块

BaseThree构造器

至于static代码块运行结果不是很清晰的童鞋,详细讲解请看这篇Static静态代码块以及各代码块之间的执行顺序

以上仅仅是让各位明确代码块之间的运行顺序,显然还是不够的,静态代码块通常用来对静态变量进行一些初始化操作,比如定义枚举类,代码如下:

public enum WeekDayEnum {

MONDAY(1,"周一"),

TUESDAY(2, "周二"),

WEDNESDAY(3, "周三"),

THURSDAY(4, "周四"),

FRIDAY(5, "周五"),

SATURDAY(6, "周六"),

SUNDAY(7, "周日");

private int code;

private String desc;

WeekDayEnum(int code, String desc) {

this.code = code;

this.desc = desc;

}

private static final Map<Integer, WeekDayEnum> WEEK_ENUM_MAP = new HashMap<Integer, WeekDayEnum>();

// 对map进行初始化

static {

for (WeekDayEnum weekDay : WeekDayEnum.values()) {

WEEK_ENUM_MAP.put(weekDay.getCode(), weekDay);

}

}

public static WeekDayEnum findByCode(int code) {

return WEEK_ENUM_MAP.get(code);

}

public int getCode() {

return code;

}

public void setCode(int code) {

this.code = code;

}

public String getDesc() {

return desc;

}

public void setDesc(String desc) {

this.desc = desc;

}

} 

当然不仅仅是枚举这一方面,还有我们熟悉的单例模式同样也用到了静态代码块,如下:

public class Singleton {

private static Singleton instance;

static {

instance = new Singleton();

}

private Singleton() {}

public static Singleton getInstance() {

return instance;

}

}

9、static变量与普通变量区别

static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

还有一点就是static成员变量的初始化顺序按照定义的顺序进行初始化。

10、静态内部类

静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:

1、它的创建是不需要依赖外围类的创建。

2、它不能使用任何外围类的非static成员变量和方法。

代码举例(静态内部类实现单例模式)

public class Singleton {

// 声明为 private 避免调用默认构造方法创建对象

private Singleton() {

}

// 声明为 private 表明静态内部该类只能在该 Singleton 类中被访问

private static class SingletonHolder {

private static final Singleton INSTANCE = new Singleton();

}

public static Singleton getUniqueInstance() {

return SingletonHolder.INSTANCE;

}

}

当 Singleton 类加载时,静态内部类 SingletonHolder 没有被加载进内存。只有当调用 getUniqueInstance()方法从而触发 SingletonHolder.INSTANCE 时 SingletonHolder 才会被加载,此时初始化 INSTANCE 实例,并且 JVM 能确保 INSTANCE 只被实例化一次。

这种方式不仅具有延迟初始化的好处,而且由 JVM 提供了对线程安全的支持。

11、静态导包

静态导包格式:import static

这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法

//  Math. --- 将Math中的所有静态资源导入,这时候可以直接使用里面的外汇代理静态方法,而不用通过类名进行调用

//  如果只想导入单一某个静态方法,只需要将换成对应的方法名即可

import static java.lang.Math.;

//  换成import static java.lang.Math.max;具有一样的效果

public class Demo {

public static void main(String[] args) {

int max = max(1,2);

System.out.println(max);

}

}

静态导包在书写代码的时候确实能省一点代码,可以直接调用里面的静态成员,但是会影响代码可读性,所以开发中一般情况下不建议这么使用。

12、static注意事项

1、静态只能访问静态。

2、非静态既可以访问非静态的,也可以访问静态的。

13、final与static的藕断丝连

到这里文章本该结束了的,但是static的使用始终离不开final字眼,二者可谓藕断丝连,常常繁见,我觉得还是很有必要讲讲,那么一起来看看下面这个程序吧。

package Demo;

class FinalDemo {

public final double i = Math.random();

public static double t = Math.random();

}

public class DemoDemo {

public static void main(String[] args) {

FinalDemo demo1 = new FinalDemo();

FinalDemo demo2 = new FinalDemo();

System.out.println("final修饰的  i=" + demo1.i);

System.out.println("static修饰的 t=" + demo1.t);

System.out.println("final修饰的  i=" + demo2.i);

System.out.println("static修饰的 t=" + demo2.t);

System.out.println("t+1= "+ ++demo2.t );

//      System.out.println( ++demo2.i );//编译失败

}

}

运行结果:

final修饰的  i=0.7282093281367935

static修饰的 t=0.30720545678577604

final修饰的  i=0.8106990945706758

static修饰的 t=0.30720545678577604

t+1= 1.307205456785776

static修饰的变量没有发生变化是因为static作用于成员变量只是用来表示保存一份副本,其不会发生变化。怎么理解这个副本呢?其实static修饰的在类加载的时候就加载完成了(初始化),而且只会加载一次也就是说初始化一次,所以不会发生变化!

————————————————

原文链接:https://blog.csdn.net/qq_44543508/article/details/102736466

原文地址:https://www.cnblogs.com/benming/p/11757981.html

时间: 2024-10-20 14:42:12

Java中static关键字的定义的相关文章

java中static关键字总结

Java中,static关键字一般情况下有四种用法: 用来修饰一个变量. 用来修饰一个方法. 用来修饰一个内部类. 用来修饰一段代码块. 1 public class Student{ 2 String name; 3 static int count;//static修饰的变量 4 static{//static修饰的代码块 5 count=0; 6 } 7 public static void playGame(){//static修饰的方法 8 System.out.println("我爱

java中static关键字解析

static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题.以下是本文的目录大纲: 一.static关键字的用途 二.static关键字的误区 三.常见的笔试面试题 若有不正之处,希望谅解并欢迎批评指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/dolphin05

Java中static关键字用法总结

1.     静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法 声明为static的方法有以下几条限制: · 它们仅能调用其他的static 方法. · 它们只能访问static数据. · 它们不能以任何方式引用this 或super. class Simple { static void go() { System.out.println("Welcome"); } } public class Cal { public static vo

[java基础]java中static关键字

1.static概念 static是静态修饰符,什么叫静态修饰符呢?大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在. 这样做有什么意义呢? 在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员,但是有种情况例外,就是该成员是用sta

Java中static关键字介绍

static关键字主要有两种作用: 第一,为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关. 第二,实现某个方法或属性与类而不是对象关联在一起 具体而言,在Java语言中,static主要有4中使用情况:成员变量.成员方法.代码块和内部类 (1)static成员变量: Java类提供了两种类型的变量:用static关键字修饰的静态变量和不用static关键字修饰的实例变量.静态变量属于类,在内存中只有一个复制,只要静态变量所在的类被加载,这个静态变量就会被分配空间,因此就可以被使

java中static关键字的理解(转载)

static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键字的用法和平常容易误解的地方,最后列举了一些面试笔试中常见的关于static的考题.以下是本文的目录大纲: 一.static关键字的用途 二.static关键字的误区 三.常见的笔试面试题 若有不正之处,希望谅解并欢迎批评指正. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.com/dolphin05

java中static关键字的作用

在java语言中有四种使用情况:成员变量.成员方法.代码块和内部类 (1)static成员变量 java中可以通过statin关键字修饰变量达到全局变量的效果.static修饰的变量(静态变量)属于类,在类第一次通过类加载器到jvm时被分配内存空间. (2)static成员方法 static修饰的方法属于类方法,不需要创建对象就可以调用.static方法中不能使用this和super等关键字,不能调用非static方法,只能访问所属类的静态成员变量和静态方法. (3)static 代码块 JVM

java中static关键字的用法

<Java编程思想(第四版)>中P86中有对static关键字的详细解释. “在static方法的内部不能调用非静态方法,反过来倒是可以.而且在没有创建任何对象的前提下,仅仅通过类本身来调用static方法,这实际上正是static方法的重要用途.” 以下通过“1.static方法:2.static变量:3.static代码块”三方面来阐述. 1.static方法: static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依

java中static关键字的使用

知识点:java中,static关键字修饰类的变量.方法.代码块.内部类 场景:我们在创建类的方法和变量时,如果这个类在创建多个对象时,共用同一个属性或者方法,就可以使用static关键字修饰,因为static修饰的变量,在内存的静态域存在的值,被类的多个实例所共用,实际上我们在编写一个类时,就是在描述对象的属性和行为,并没有产生实质上的对象,只有使用new关键字,才会产生对象,这时系统才会分配内存给对象,其方法才可以供外部调用.如果让多个对象共用内存空间的一份数据,就可以使用static关键字