当前位置: 首页 > backend >正文

static关键字

思维导图:

  

在 Java 中,static 是一个非常重要的关键字,它可以用来修饰类的成员,包括变量、方法、代码块以及内部类。下面为你详细介绍 static 关键字的各种用法和特点。

一.修饰内部类

  静态内部类:当 static 修饰内部类时,这个内部类就成为了静态内部类。静态内部类不依赖于外部类的实例,可以直接创建。它只能访问外部类的静态成员,因为静态内部类在加载时可能还没有创建外部类的实例。

代码示例:

class Outer {static int outerStaticVariable = 10;int outerInstanceVariable = 20;// 静态内部类static class StaticInner {public void display() {// 可以访问外部类的静态成员System.out.println("Outer static variable: " + outerStaticVariable);// 以下代码会编译报错,因为静态内部类不能访问外部类的实例成员// System.out.println("Outer instance variable: " + outerInstanceVariable); }}
}public class Main {public static void main(String[] args) {// 可以直接创建静态内部类的实例Outer.StaticInner inner = new Outer.StaticInner();inner.display();}
}

说明:

  StaticInner是Outer 类的静态内部类。在 StaticInner 类的 display 方法里,可以访问外部类的静态变量 outerStaticVariable,但不能访问外部类的实例变量 outerInstanceVariable在 Main 类的 main 方法中,可以直接创建 Outer.StaticInner 类的实例,无需先创建 Outer 类的实例。
 

  static关键字不能修饰顶层类(直接定义在包中的类)。

代码示例:

// 以下代码会编译报错,因为 static 不能修饰顶层类
// static class TopLevelClass {
//     public void method() {
//         System.out.println("This is a top - level class.");
//     }
// }

  原因:顶层类代表一个独立的实体,其设计目的是为了被其他类继承或者实例化,从而实现不同的功能。而 static 关键字的作用是将成员和类相关联,而非和类的实例相关联。若将顶层类用 static 修饰,就会违背顶层类的设计初衷,所以 Java 语法不允许使用 static 修饰顶层类。

二.修饰成员变量和成员方法

2.1修饰成员变量

public class StaticTest01 {//修饰成员变量,此时是静态变量private static int age;private static String name;private static int number1 = 10;//实例变量private int number2 = 20;public static void main(String[] args) {StaticTest01.setAge(18);StaticTest01.setName("张三");//访问成员变量   类名.变量名System.out.println(StaticTest01.getAge() + "->" + StaticTest01.getName());}
}

2.2修饰成员方法同理

访问方式: 类名.方法名

2.3修饰代码块

public class StaticTest01 {private static int number1 = 10;private int number2 = 20;static {System.out.println(number1);  //number1是静态的
//      System.out.println(number2);  //编译错误 静态不能访问实例变量}

注意:在实例方法,实例代码块中可以访问类变量,类方法;但是类变量,类方法,静态代码块不可以访问实例方法,实例变量,实例代码块。

原因:

  1. 静态方法/变量/代码块和类强相关;它不依赖于对象,在类加载时,静态方法/变量/代码块就被加载到内存中,无需创建类的实例就能调用。
  2. 实例方法/变量/代码块和实例对象强相关。调用实例方法/变量时,必须通过类的实例来调用,(对象的引用来调用)。

2.4static不能修饰构造方法 

public class StaticTest01 {//     public static StaticTest01() {
//         static不能修饰构造方法
//     }
}

不能用 static 修饰构造方法的原因

  1. 语义冲突:构造方法的目的是创建并初始化对象,而静态成员是属于类本身,不依赖于实例。如果构造方法被 static 修饰,这就与构造方法创建实例的初衷相违背。因为静态方法可以在没有创建任何实例的情况下被调用,若构造方法是静态的,那么就无法通过它来初始化特定的实例。
  2. 逻辑矛盾:构造方法在对象创建时自动调用,并且与具体的对象实例相关联。而静态方法没有 this 引用,this 引用指向调用该方法的对象实例。如果构造方法是静态的,就不存在 this 引用,也就无法对特定的对象实例进行初始化操作。
  3. 设计原则:从设计角度来看,构造方法和静态方法有着不同的职责。构造方法负责对象的创建和初始化,而静态方法通常用于执行与类相关的通用操作,不涉及特定对象的状态。将两者区分开来可以使代码更加清晰和易于维护。

三.构造方法,静态代码块,普通代码块的执行流程

执行流程

当创建一个类的对象时,执行流程如下:

  1. 先进行类的加载,此时会执行静态代码块。静态代码块在类加载时只执一次。
  2. 创建对象实例,在调用构造方法之前,会先执行实例代码块。
  3. 执行构造方法完成对象的初始化。

代码示例:

public class Parent {public Parent() {System.out.println("父类构造方法执行");}{System.out.println("父类普通代码块执行");}static {System.out.println("父类静态执行");}
}public class Child extends Parent {public Child() {System.out.println("子类构造方法执行");}{System.out.println("子类普通代码块执行");}static {System.out.println("子类静态执行");}public static void main(String[] args) {Parent parent = new Child();System.out.println("=========证明static修饰的代码只会执行一次============");Parent parent2 = new Child();}
}

运行结果:

四.static成员的继承

4.1静态成员变量的继承

静态成员变量属于类,而非类的某个实例。当子类继承父类时,会继承父类的静态成员变量。不过,子类和父类实际上共享同一份静态成员变量,这意味着无论通过父类还是子类来访问或修改静态成员变量,操作的都是同一个变量。

代码示例:

class Parent {static int staticVariable = 10;
}class Child extends Parent {// 继承了 Parent 类的 staticVariable
}public class Main {public static void main(String[] args) {System.out.println(Parent.staticVariable); // 输出 10System.out.println(Child.staticVariable);  // 输出 10Child.staticVariable = 20;System.out.println(Parent.staticVariable); // 输出 20System.out.println(Child.staticVariable);  // 输出 20}
}

在上述代码中,Child类继承了Parent类的staticVariable 静态成员变量。当通过 Child 类修改staticVariable 的值后,再通过 Parent 类访问该变量,得到的是修改后的值,这表明它们共享同一份静态成员变量。

4.2静态方法的继承

静态方法同样属于类,子类可以继承父类的静态方法。子类可以直接使用父类的静态方法,也可以定义与父类同名的静态方法,不过这并非方法重写(Override),而是方法隐藏(Hide)。方法隐藏是指子类定义了与父类同名、同参数列表的静态方法,此时通过子类调用该方法时,调用的是子类的方法;通过父类调用该方法时,调用的是父类的方法。

代码示例:

class Parent {static void staticMethod() {System.out.println("Parent's static method");}
}class Child extends Parent {static void staticMethod() {System.out.println("Child's static method");}
}public class Main {public static void main(String[] args) {Parent.staticMethod(); // 输出 "Parent's static method"Child.staticMethod();  // 输出 "Child's static method"Parent parent = new Child();parent.staticMethod(); // 输出 "Parent's static method",因为静态方法根据引用类型调用}
}

在上述代码中,Child 类定义了与 Parent类同名的静态方法 staticMethod,这是方法隐藏。当通过 Parent 类引用调用 staticMethod 时,调用的是 Parent 类的方法;当通过 Child 类引用调用 staticMethod 时,调用的是 Child 类的方法。
 

总结:

 Java类中包含了成员变量、成员方法、构造方法、初始化块和内部类(包括接口、枚举)5种成员,static关键字可以修饰除了构造方法外的其他4种成员。static关键字修饰的成员被称为类成员。类成员属于整个类,不属于单个对象。 static关键字有一条非常重要的规则,即类成员不能访问实例成员,因为类成员属于类的,类成员的作用域比实例成员的作用域更大,很容易出现类成员初始化完成时,但实例成员还没被初始化,这时如果类成员访问实力成员就会引起大量错误。

 static修饰的部分会和类同时被加载。被static修饰的成员先于对象存在,因此,当一个类加载完毕,即使没有创建对象也可以去访问被static修饰的部分。 静态方法中没有this关键词,因为静态方法是和类同时被加载的,而this是随着对象的创建存在的。静态比对象优先存在。也就是说,静态可以访问静态,但静态不能访问非静态,而非静态可以访问静态。

http://www.xdnf.cn/news/271.html

相关文章:

  • qt QGroupButton 实现两个QPushButton的互斥
  • 动态计算FPS(每秒帧数)的方法
  • Jsp技术入门指南【六】jsp脚本原理及隐式对象
  • 关于AI提示工程的详解,分点说明其核心概念、关键技巧和应用场景
  • 语音合成之二TTS模型损失函数进化史
  • 极狐GitLab 项目和群组的导入导出速率限制如何设置?
  • Linux 文件查找终极指南:find, locate, grep 等命令详解
  • 18-算法打卡-哈希表-两数之和-leetcode(1)-第十八天
  • 智能体时代的产业范式确立,中国企业以探索者姿态走出自己的路
  • [密码学实战]详解gmssl库与第三方工具兼容性问题及解决方案
  • Python语言基础教程(上)4.0
  • 15.4K Star!Vercel官方出品,零基础构建企业级AI聊天机器人
  • 进程(转账,卖票)
  • C#核心笔记——(六)框架基础
  • 【MySQL】数据库和表的操作详解
  • 6.6 “3步调用ChatGPT打造高可靠Python调度器,零依赖实现定时任务自动化“
  • Linux工具学习之【vim】
  • 医学图像中的不同模态图像详细介绍
  • VirtualBox导入 .ova 文件出错,怎么解决
  • Java入门-Map双列集合
  • 通过C# 将Excel表格转换为图片(JPG/ PNG)
  • 51单片机实验七:EEPROM AT24C02 与单片机的通信实例
  • 《计算机视觉度量:从特征描述到深度学习》—工业检测大模型RAG白皮书
  • 12芯束装光纤不同包层线颜色之间的排列顺序
  • Linux 内核开发/测试工具对比 Windows 驱动验证工具 (Driver Verifier)
  • 从数据集到开源模型,覆盖无机材料设计/晶体结构预测/材料属性记录等
  • 70. 爬楼梯
  • 环境搭建与入门:Flutter SDK安装与配置
  • 《数据结构初阶》【时间复杂度 + 空间复杂度】
  • Echart 地图放大缩小