static关键字的使用

static 关键字可以用来修饰属性、方法和语句块等

  1. static 修饰变量,该变量称为类变量或静态变量,全局只有一份。
  2. static 修饰方法,该方法称为静态方法,可以无须和对象绑定,通过类名加点直接访问。
  3. 注意,static 不可以修饰构造方法。
  4. static 修改语句块,该块称为静态块,加载类时只执行一次。
  5. 不管是静态方法还是静态块,在静态的区域中外部非静态的成员不能进行访问。

static 关键字可以用来修饰属性,也就是用来修饰变量。

在类中被 static 关键字修饰的变量,我们称之为 "类变量" 或是 "静态变量"。

语法结构:在数据类型之前加上 static 关键字。

arduino 复制代码
[private|public|protected] static 数据类型 变量名;

通过代码具体来看一下吧。 😀

在全局中,也就是类体中声明两个变量,如下:

ini 复制代码
//成员变量
int i = 10;
//静态变量、类变量
static int j = 20;

然后,在主入口 main 方法中进行变量打印:

csharp 复制代码
System.out.println(j);
System.out.println(i);

程序在编译的时候出错了,告诉我们 "无法从静态上下文中引用非静态变量 i" ,从错误的提示信息中我们可以看到,i 在 main 方法中是无法直接访问的,需要和对象绑定才可以使用;但是 j 没有问题,可以在 main 方法中直接使用。

🤔 那么要如何修改,才能使用呢?

变量 i 需要和对象绑定才能访问。

ini 复制代码
System.out.println(j);
TestStatic ts = new TestStatic();
System.out.println(ts.i);

这样编译就能通过了,打印输出「20」 「10」。

接着,我们再来看一段代码,声明的 i 和 j 变量不变。

ini 复制代码
TestStatic ts1 = new TestStatic();
TestStatic ts2 = new TestStatic();
System.out.println(ts1.i);
System.out.println(ts1.j);
System.out.println(ts2.i);
System.out.println(ts2.j);

创建两个 TestStatic 对象 ts1 和 ts2 ,分别调用 i 和 j ,运行结果如下:

对于这个结果我想大家应该没有问题吧。

接着,我们使用 ts1 对象调用 i 赋值 100,使用 ts2 对象调用 j 赋值 200,再来打印分别调用的 i 和 j 。

ini 复制代码
ts1.i = 100;
ts2.j = 200;

System.out.println(ts1.i);
System.out.println(ts1.j);
System.out.println(ts2.i);
System.out.println(ts2.j);

运行结果如下图:

ts1.i 的值为 100,而 ts2.i 的值为 10,因为两个不同的对象,成员变量各自有一份;然而,ts1.jts2.j 的值都是 200,因为静态变量 j 全局只有一份。

然后,我们在打印之前的变量 ts.i 和 j,看看结果如何?

csharp 复制代码
System.out.println(j);
System.out.println(ts.i);

运行结果图:

从以上一系列的结果,我们可以总结出:

  • 成员变量,每个对象各自有一份。
  • 静态变量或类变量,全局只有一份。

好了,同学们在 /home/project 目录下,创建 TestStatic.java 源文件,代码如下:

ini 复制代码
/**
 * static 关键字修饰变量的使用
 * @author 小桃子
 */
public class TestStatic{
    //成员变量
    int i = 10;
    //静态变量、类变量
    static int j = 20;

    public static void main(String[] args) {
        System.out.println(j);
        TestStatic ts = new TestStatic();
        System.out.println(ts.i);
                // 创建不同的 TestStatic 对象进行变量访问
        TestStatic ts1 = new TestStatic();
        TestStatic ts2 = new TestStatic();
        System.out.println(ts1.i);
        System.out.println(ts1.j);
        System.out.println(ts2.i);
        System.out.println(ts2.j);
                // 不同的对象对 i 和 j 进行赋值
        ts1.i = 100;
        ts2.j = 200;
                // 打印不同对象的 i 和 j 变量
        System.out.println(ts1.i);
        System.out.println(ts1.j);
        System.out.println(ts2.i);
        System.out.println(ts2.j);

        System.out.println("----");
        System.out.println(j);
        System.out.println(ts.i);
    }
}

static 关键字修饰方法,我们称之为 "静态方法"。

其实我们一直到使用的 main 方法就是一个被 static 修饰的静态方法。

成员变量 i 不能直接在 main 方法中使用,就说明非静态成员不能在静态方法中使用

语法结构:在方法返回类型之前加上 static 关键字。

arduino 复制代码
[public|protected|private] static 返回值类型 方法名(参数列表){
    方法体
}

/home/project 目录下,创建 TestStatic2.java 源文件,在类加入普通方法和静态方法,我们作一个对比。

类全局中还是声明成员变量 i 和静态变量 j ,进行使用。

ini 复制代码
public static void method1(){
  i = 1000;
  j = 2000;
  method2();
  static int k = 40;
  int k = 40;
}
public void method2(){
  i = 150;
  j = 231;
  method1();
}

我们先来看一下编译结果,如下图:

静态方法 method1() 中,非静态的成员都不能再静态方法中进行访问;在方法中都不能再声明静态的变量。

method2() 是非静态方法,它可以访问外部的静态和非静态的成员。

我们声明静态方法,其中一个目的是,它的调用不在需要和对象进行绑定,直接可以通过类名访问。

scss 复制代码
TestStatic2.method1();
new TestStatic2().method2();

TestStatic2.java 源代码如下:

ini 复制代码
/**
 * static 关键字修饰方法的使用
 * @author 小桃子
 */
public class TestStatic2 {
    int i = 10;
    static int j = 20;

    /**
     * 静态方法中不能访问外部非静态的成员
     */
    public static void method1(){
      // i = 1000;
      j = 2000;
      // method2();
      // static int k = 40;
      int h = 40;
    }
    /**
       * 非静态方法中可以访问外部静态和非静态的成员
       */
    public void method2(){
      i = 150;
      j = 231;
      method1();
    }

    public static void main(String[] args) {
        TestStatic2.method1();
        new TestStatic2().method2();
    }
}

静态的方法,其实之前的用过的 String 类中的 valueOf(),包装类中有好多静态方法,如:parseInt() 等等。

static 关键字还可以修饰语句块,被 static 关键字修饰的语句块我们称之为静态块,否则称之为初始化块。

语法结构:在语句块之前加上 static 关键字。

arduino 复制代码
static {
  // 静态区域中不能访问外部非静态的成员
}

/home/project 目录下,创建 TestStatic3.java 源文件,代码如下:

csharp 复制代码
/**
 * static 关键字修饰语句块的使用
 * @author 小桃子
 */
public class TestStatic3 {
    // 类加载时只执行一次
    static{
        System.out.println("静态块");
    }
    // 每次创建对象时都会被加载
    {
        System.out.println("初始化块");
    }
    public static void main(String[] args) {
        new TestStatic3();
        new TestStatic3();
    }
}

🌟 注意:

  • 对静态块而言,只要加载该类,就会执行静态块的内容,但只会执行一次。
  • 对初始化块而言,只有创建对象时,会去执行的部分,创建 n 个对象,就执行初始化块 n 次。

运行结果如下图:

相关推荐
Bony-3 分钟前
Go语言反射从入门到进阶
开发语言·后端·golang
凡人的AI工具箱1 小时前
每天40分玩转Django:Django Email
数据库·人工智能·后端·python·django·sqlite
后端转全栈_小伵1 小时前
SQLite本地数据库的简介和适用场景——集成SpringBoot的图文说明
数据库·spring boot·后端·sqlite·学习方法
undeflined1 小时前
vite + vue3 + tailwind 启动之后报错
开发语言·后端·rust
猿来入此小猿2 小时前
基于SpringBoot在线音乐系统平台功能实现十七
java·spring boot·后端·毕业设计·音乐系统·音乐平台·毕业源码
重整旗鼓~2 小时前
2.flask中使用装饰器统一验证用户登录
后端·python·flask
it噩梦3 小时前
springboot 工程使用proguard混淆
java·spring boot·后端
从种子到参天大树3 小时前
SpringBoot源码阅读系列(二):自动配置原理深度解析
后端
斯joy杰4 小时前
JavaWeb篇——Web工作流程、请求响应
java·后端
狠难说4 小时前
SpringCloud(八) - 自定义token令牌,鉴权(注解+拦截器),参数解析(注解+解析器)
后端