大家都知道,我们可以基于一个类创建多个该类的对象,每个对象都拥有自己的成员,互相独立。然而在某些时候,我们更希望该类所有的对象共享同一个成员。此时就是 static 大显身手的时候了!!

Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,(这块涉及到JVM的内存模型,静态成员在堆内存的永久带)即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问。当然,鉴于他作用的特殊性更推荐用类名访问~~

例如:

  1. public class HelloWorld {
  2.  
  3. // 定义静态变量,保存班级名称
  4. static String className = "JAVA开发一班";
  5.  
  6. public static void main(String[] args) {
  7.  
  8. // 访问静态变量,输出班级名称
  9. System.out.println(HelloWorld.className );
  10. HelloWorld helloWorld = new HelloWorld();
  11. System.out.println(helloWorld.className) ;
  12. }
  13. }

使用 static 可以修饰变量、方法和代码块。

需要注意:

1、 静态方法中可以直接调用同类中的静态成员,但不能直接调用非静态成员,如果要想在静态方法中调用非静态变量,可以通过实例化对象,通过对象.属性访问对象的属性。

例如:

  1. public class HelloWorld {
  2.  
  3. // 定义静态变量score1
  4. static int score1 = 86;
  5. String name = "张三" ;
  6. public static void main(String[] args) {
  7. System.out.println(HelloWorld.score1);
  8. System.out.println(HelloWorld.name); //此处的代码在idea会直接报错。在静态方法中不能访问非静态变量。可以通过实例化对象,通过对象访问。
  9. HelloWorld helloWorld = new HelloWorld();
  10. System.out.println(helloWorld.name);
  11. }
  12. }

静态代码块

我们知道,Java 中可以通过初始化块进行数据赋值

例如:

  1. public class HelloWorld {
  2.  
  3. String name ; //定义成员变量
  4. {
  5. name = "zhangsan"; //在初始化块中初始化成员变量的值。
  6. }
  7. }

在类的声明中,可以包含多个初始化块,当创建类的实例时,就会依次执行这些代码块。如果使用 static 修饰初始化块,就称为静态初始化块。

需要特别注意:静态初始化块只在类加载时执行,且只会执行一次,同时静态初始化块只能给静态变量赋值,不能初始化普通的成员变量。

上面这段红字标注的很重要,解读一下,创建类的实例(new 类的时候),初始化块new一次就会执行一次,但是static修饰的只会执行一次,因为他是属于类成员,只在类加载的时候初始化一次,所以不管new多少次,static 修饰的代码块只会执行一次。(这块如果对jvm的内存模型不理解,可能感觉有点抽象。后面我们会有专门博客介绍jvm内存模型)

上面的说明的例子如下:

  1. public class HelloWorld {
  2.  
  3. String name; // 声明变量name
  4. String sex; // 声明变量sex
  5. static int age;// 声明静态变量age
  6.  
  7. // 构造方法
  8. public HelloWorld() {
  9. System.out.println("通过构造方法初始化name");
  10. name = "tom";
  11. }
  12.  
  13. // 初始化块
  14. {
  15. System.out.println("通过初始化块初始化sex");
  16. sex = "男";
  17. }
  18.  
  19. // 静态初始化块
  20. static {
  21. System.out.println("通过静态初始化块初始化age");
  22. age = 20;
  23. }
  24.  
  25. public static void main(String[] args) {
  26. // 创建对象
  27. HelloWorld hello = new HelloWorld();
  28. HelloWorld h1 = new HelloWorld();
  29.  
  30. }
  31. }

运行这个例子,我还想证明一个问题,构造方法,初始化块,静态代码块,执行的先后顺序,及上面初始化块每次实例化都会执行,static修饰的静态代码块只会执行一次。

执行结果如下:

  1. 通过静态初始化块初始化age
  2. 通过初始化块初始化sex
  3. 通过构造方法初始化name
  4. 通过初始化块初始化sex
  5. 通过构造方法初始化name

由上面的执行结果,我们可以看出,静态代码块最先执行,初始化块,构造方法依次。并且初始化块和构造方法每次实例化都会执行,静态代码块只会执行一次。

再深入一点,子类和父类,都含有静态代码块,代码块,构造函数,在new子类的过程中,上面子类父类的(静态代码块,代码块,构造函数)初始化顺序顺序是如何的?

  1. package com.sysware.cloud.acl.controller;
  2.  
  3. /**
  4. * Created by tianwenqing on 2019/4/1.
  5. */
  6. public class Parent{
  7.  
  8. /**
  9. * 静态代码块
  10. */
  11. static {
  12. System.out.println("执行了父类静态代码块....");
  13. }
  14.  
  15. /**
  16. * 代码块
  17. */
  18. {
  19. System.out.println("执行了父类代码块");
  20. }
  21.  
  22. private String name ;
  23. private Integer age ;
  24.  
  25. public Parent(){
  26.  
  27. System.out.println("执行了父类构造函数");
  28. }
  29.  
  30. public String getName() {
  31. return name;
  32. }
  33.  
  34. public void setName(String name) {
  35. this.name = name;
  36. }
  37.  
  38. public Integer getAge() {
  39. return age;
  40. }
  41.  
  42. public void setAge(Integer age) {
  43. this.age = age;
  44. }
  45. }

子类:

  1. package com.sysware.cloud.acl.controller;
  2.  
  3. /**
  4. * Created by tianwenqing on 2019/4/1.
  5. */
  6. public class Parent{
  7.  
  8. /**
  9. * 静态代码块
  10. */
  11. static {
  12. System.out.println("执行了父类静态代码块....");
  13. }
  14.  
  15. /**
  16. * 代码块
  17. */
  18. {
  19. System.out.println("执行了父类代码块");
  20. }
  21.  
  22. private String name ;
  23. private Integer age ;
  24.  
  25. public Parent(){
  26.  
  27. System.out.println("执行了父类构造函数");
  28. }
  29.  
  30. public String getName() {
  31. return name;
  32. }
  33.  
  34. public void setName(String name) {
  35. this.name = name;
  36. }
  37.  
  38. public Integer getAge() {
  39. return age;
  40. }
  41.  
  42. public void setAge(Integer age) {
  43. this.age = age;
  44. }
  45. }

测试类:

  1. package com.sysware.cloud.acl.controller;
  2.  
  3. /**
  4. * Created by tianwenqing on 2019/4/1.
  5. */
  6. public class Test {
  7.  
  8. public static void main(String[] args) {
  9. Child child = new Child();
  10. System.out.println("第二次new........");
  11. Child child1 = new Child();
  12.  
  13. }
  14. }

输出结果如下:

如图可知初始化顺序为:先父类的静态代码块--》子类的静态代码块--》父类的代码块--》父类的构造函数--》子类的代码块--》子类的构造函数。

static 关键字介绍的更多相关文章

  1. Java中static关键字介绍

    static关键字主要有两种作用: 第一,为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关. 第二,实现某个方法或属性与类而不是对象关联在一起 具体而言,在Java语言中,static ...

  2. c/c++中static与extern关键字介绍

    一.C语言中的static关键字 在C语言中,static可以用来修饰局部变量,全局变量以及函数.在不同的情况下static的作用不尽相同. (1)修饰局部变量 一般情况下,对于局部变量是存放在栈区的 ...

  3. Java中的static关键字和new关键字作用介绍

    一.static关键字的作用 1.可以用于修改类的成员变量.代码块和类 通过static可以将类的成员声明为静态成员,静态的成员归属于整个类,而不是属于某个对象.无论通过类还是对象访问静态成员,操作的 ...

  4. C/C++中static关键字详解

    静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值. 静态变量或静态函数只有本文件内的代码才能访问它,它的名字在其它文件中不可见.用法1:函数内部声明 ...

  5. C/C++中static关键字详解-zz

    静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值. 静态变量或静态函数只有本文件内的代码才能访问它,它的名字在其它文件中不可见.用法1:函数内部声明 ...

  6. ava下static关键字用法详解

    Java下static关键字用法详解 本文章介绍了java下static关键字的用法,大部分内容摘自原作者,在此学习并分享给大家. Static关键字可以修饰什么? 从以下测试可以看出, static ...

  7. (转)C/C++中static关键字

    下面的转自http://www.cnblogs.com/yc_sunniwell/archive/2010/07/14/1777441.html 静态变量作用范围在一个文件内,程序开始时分配空间,结束 ...

  8. 【转载】static关键字详解

    上一篇博客中,因为一个static关键字没有设置好,导致浪费了大量的时间来寻找程序的错误,归根结底,就是大一的时候c语言没有学好. 现在总算知道了,你现在所学的每一个知识点在不就的以后可能及时你的救命 ...

  9. Java static 关键字详解

    引言 在<Java编程思想>中有这样一段话:static方法就是没有this的方法.在static方法内部不能调用非静态方法,反过来是可以的.而且可以在没有创建任何对象的前提下,仅仅通过类 ...

随机推荐

  1. win10 字体渲染优化 色彩调整

    最近烧包买了个2k显示器,发现跟win10使用,一堆问题,最大的就是字体,其实应该买4k,那样正好设置200%字体,现在设置的124% 字体: 以前使用的是mactype这个软件 https://pa ...

  2. HDU 1874 畅通工程续(最短路训练

    因为数据比较小 所以flyod spfa dijkstra 多可以过 Floyd #include <bits/stdc++.h> using namespace std; const i ...

  3. Windows 上安装 pip

    1 从  https://pypi.python.org/pypi/pip#downloads  下载安装包 pip-9.0.1.tar.gz 2 解压 pip-9.0.1.tar.gz 3 用CMD ...

  4. NOIP2018 退役记

    NOIP挂完,OI再见 AFO Day 0 早上的高铁,1点多到广州,2点多到酒店,下午就是颓颓颓,然后晚上随便刷了一下板子,反正PJ也没啥板子可以刷 就这样浪费了一天,我到底在干嘛 Day 1 早上 ...

  5. java web项目配置https访问

      转载: tomcat6配置:  1.单向认证,就是传输的数据加密过了,但是不会校验客户端的来源  2.双向认证,如果客户端浏览器没有导入客户端证书,是访问不了web系统的,找不到地址  如果只是加 ...

  6. 【TCP/IP详解 卷一:协议】第二章:链路层

    2.1 引言 链路层的三个目的: (1)为IP模块发送和接收IP数据报. (2)为ARP模块发送ARP请求和接收ARP应答.地址解析协议:ARP. (3)为RARP模块发送RARP请求和接收RARP应 ...

  7. 怎样借助Python爬虫给宝宝起个好名字--python 学习

    每个人一生中都会遇到一件事情,在事情出现之前不会关心,但是事情一旦来临就发现它极其重要,并且需要在很短的时间内做出重大决定,那就是给自己的新生宝宝起个名字. 因为要在孩子出生后两周内起个名字(需要办理 ...

  8. python 阶乘

    product= i= : product=i*product print('i=%d' %i,end='') print('\tproduct=%d' %product) i+= print('\n ...

  9. Selenium 定位页面元素 以及总结页面常见的元素 以及总结用户常见的操作

    1. Selenium常见的定位页面元素 2.页面常见的元素 3. 用户常见的操作 1. Selenium常见的定位页面元素 driver.findElement(By.id());driver.fi ...

  10. MVC 子对象数据传递

    1.接受参数 public ActionResult Address(User user) { return View(); } 2. User对象类型 public class User { pub ...