01.Java关键字与底层原理-static关键字

1.static关键字

1.1.含义

static方法就是没有this的方法,在static方法的内部不能调用非静态的方法,反过来倒是可以。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法,这实际上正是static方法的主要用途。[1]
简单来说,就是不需要创建对象就能访问static修饰的方法,而static修饰的方法却不能直接调用非静态的方法。static关键字不仅仅能修饰方法,还可以修饰变量,那么引申开来,就是可以通过类直接访问由static修饰的变量。

当然这只是其中的两个应用的方向,static关键字不仅仅能修饰方法和变量,还可以修饰代码块、类以及做静态导包使用,这其中的含义将在用法当中解释。对于没有写static的关键字的构造方法,以及接口里面的变量,他们都是具有static特性的,也在下面做一并的描述。

1.2.用法与底层原理

1.2.1.static变量

  • 用法

static变量,就是不需要创建对象,直接通过类就能访问的变量。访问的形式为 类名.变量名,在类加载的时候就完成初始化,内存当中只有一份,所有的对象都共享这一个变量。需要对象之间共享变量的时候使用。

public class Static{
  public static String staticVal = "static";
}
public class Main{
  public void method1() {
    System.out.println(Static.staticVal);
  }
}
  • 底层原理

这是一个简化版的内存解释,Java的内存包含了栈、堆和静态存储区,栈主要是存放对象的应用,堆是放对象,而静态存储区主要是放一些方法和常量。那么,如果我们有以下的对象:

public class Person{
  public String name;
  public static Integer age;
}
public class Main{
  public static void main(String[] args) {
    Person person = new Person();
    person.name = "wusicheng";
    person.age = 18;
  }
}

那么他们在内存当中的分配情况如下图所示:


注意nameage存储位置的不同,name是存储存储到堆上面的,和对象绑定在一起,而age是Person类进行管理的,存储在静态存储区上面,不论建立多少个对象,都只指向这个一个地方。在类加载的时候,静态存储区中的内容已经初始化完成,所以在内存当中就只有这一份。

1.2.2.static方法

static方法就是可以使用 对象.方法名(方法参数...) 进行访问的方法,静态方法当中,不可以直接调用非静态的方法。具体的使用如下

public class Static{
  public void notStatic() {
    //todo
  }
  public static void staticMethod() {
    System.out.println("===静态方法===");
    notStatic();//error 不可以这么调用,会报错
  }
}
public class Main{
  public void method1() {
    Static.staticMethod();
  }
}
  • 底层原理

略,后面进行补充。

1.2.3.static代码块

static静态代码块的作用是初始化一些静态变量使用的,在static代码块里面,可以调用静态变量方法。

public class Static{
  public static List<String> staticList = new ArrayList<>(2);
  static {
    staticList.add("static1");
    staticList.add("static2");
  }
}
public class Main{
  public void method1() {
    System.out.println(Static.staticList.get(0));
  }
}
  • 底层原理

略,以后补充。

1.2.4.static类

static修饰类,只能够在静态内部类当中使用,所谓的静态内部类,就是在类里面套一层类,并且这个类是使用static修饰的。这样做可以把一个类隐藏到外部类里面,而且不需要内部类引用外围类对象。

public class Static{
  public static class InnerStaticClass {
    public void method() {
      System.out.println("===InnerStaticClass====");    
    }
  }
}
public class Main{
  public void method1() {
    Static.InnerStaticClass innerClass = new Static.InnerStaticClass();
  }
}

1.2.5.静态导包

静态导包是简化书写使用的,使用了静态导包之后,就可以直接使用相关的静态变量,静态方法,不需要使用类名.变量类名.方法来进行调用,一般的使用场景是junit判断是否相等的情况下使用。

import static java.lang.Math.PI;
public void method() {
    System.out.println(PI);
}

1.2.6.接口当中的变量

接口当中可以定义成员变量,而且定义的成员变量一定是public static final的,但是在实际的书写过程中,可以把public static final给去掉,例如下面的两种写法是一样的。

public interface StaticInterface {
    String staticVal = "static val in interface";
    public static final String staticVal2 = "static val in interface";
}
public class Main {
    public void mehod() {
        /**接口当中的变量*/
        System.out.println(StaticInterface.staticVal);
        System.out.println(StaticInterface.staticVal2);
    }
    public static void main(String[] args) {
        new Main().mehod();
    }
}
  • 底层原理

略,后面补上。

1.3. 实际应用

static关键字,一般都是用在工具类里面,工具类只需要一套,载入内存的时候对这些变量和方法进行初始化就可以了,不需要每一次都创建对象,然后调用相应的变量和方法,否则会浪费过多的内存资源。但是,如果static的变量和方法太多,而这些变量和方法是在JVM关闭的时候才进行清理的,在就会造成内存的浪费,而且可以回导致内存溢出。

对于程序当中常用的变量,而且基本不需要变更的,也可以使用static关键字进行修饰然后使用static静态代码块进行初始化,那么程序在调用的时候就可以直接在内存中拿来就用,不需要再堆上面再分配空间,然后初始化成一样的数据,这样会降低效率而且会浪费内存。基于这个原因,JUnit使用@BeforeClass注解的方法,必须是static方法的原因就显而易见了,因为在单元测试当中,@BeforeClass是在单元测试载入时候初始化相关的数据使用的,而且这些数据是一整类都通用,那么让他们初始化到内存当中,用的时候直接调可以大大节约时间和空间。

1.4. 总结

  1. static关键字修饰的会在类加载完成的时候就初始化到内存当中,直到JVM关闭;
  2. static关键字修饰的变量和方法是通过"类名.变量"和"类名.方法"调用的;
  3. static方法当中不能使用this,它是类管理的,不是对象管理的,同时也不能使用super;
  4. 接口里面的成员变量默认都是public static final的;
  5. static关键字常用在工具类当中或者只需要初始化一次的方法上。

https://www.jianshu.com/p/92327e300a6e


  1. 来自《Java编程思想》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,635评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,543评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,083评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,640评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,640评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,262评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,833评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,736评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,280评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,369评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,503评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,870评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,340评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,460评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,909评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,512评论 2 359

推荐阅读更多精彩内容