(结合Java语言程序设计第12版-9.7)
本篇文章主要讲解static关键字,内容从概述和用法两点来讲解,关于概述大家能理解就可以,用法是它的重点。

概念

static翻译过来就是静态的意思

  • 静态的

    作用

  • Java中static可以修饰类的成员

    static既可以修饰对应类里面的成员变量,也可以修饰类里面的方法。

  • 被static修饰的内容就不再属于这个对象了,而是属于这个类。

    static修饰的成员变量叫静态变量「static variable」,也叫类变量「class variable」。
    static修饰的方法叫静态方法,也叫类方法。

下面👇,我们分别来看一下对应的静态变量和静态方法。

静态变量

首先,我们来看一下对应的静态变量。上面介绍的时候说到了,静态变量就是static修饰的成员变量。

无论是我们产生多少个对象,对应某些特定的属性值在内存空间中只有一份,那就是静态变量的属性值。

调用方式

  1. 类名.静态变量名

特点

静态变量「static variable」的特点就是让一个类的所有实例都共享数据

被static修饰的内容就不再属于某一个对象了,而是属于类

变量值存储在一个公共的内存地址

说明

需求一
  • 想要一个类的所有实例共享数据,怎么解决??

    定义质量控制部类,让每位测试工程师进行自我介绍

效果如图:
关键字:static - 图1

分析
  • 质量控制部成员统称为测试工程师,定义类名为TestEngineer
  • 定义TestEngineer类的每个人普通的属性和行为:

当我们创建一个实体类的时候,其实就是描述这个实体类的相关属性和行为,属性就是对应的成员变量,行为就是在该实体类中的具体实现的方法,但是没有产生实质性的对象。

只有通过new关键字来创建的时候,对应的系统才会分配相对应的内存空间给对象,这样该对象的属性和方法才能被外部使用。

  1. package top.testeru.keywords.staticp;
  2. /**
  3. * @Package: top.testeru.keywords.staticp
  4. * @author: testeru.top
  5. * @Description: 定义质量控制部类,让每位测试工程师进行自我介绍
  6. * @date: 2022年02月15日 10:53 AM
  7. */
  8. //质量控制部
  9. public class TestEngineer {
  10. //姓名
  11. private String name;
  12. //工作内容
  13. private String work;
  14. //部门名
  15. private String department;
  16. //成员方法
  17. //进行自我介绍
  18. public void selfIntroduction(){
  19. System.out.println("我是" + getName() +",我的工作是"+ getWork() +",我所属部门是"+ getDepartment());
  20. }
  21. public String getDepartment() {
  22. return department;
  23. }
  24. public void setDepartment(String department) {
  25. this.department = department;
  26. }
  27. public String getName() {
  28. return name;
  29. }
  30. public void setName(String name) {
  31. this.name = name;
  32. }
  33. public String getWork() {
  34. return work;
  35. }
  36. public void setWork(String work) {
  37. this.work = work;
  38. }
  39. }
  • 由上面看到每位测试工程师所属的部门相同,所以属性department可以直接在TestEngineer中赋值为质量控制部
  1. private String department = "质量控制部";

关键字:static - 图2

可以看到对应也是同样的显示效果,但是有一个问题,如果说有成员自己突然修改了部门,对应的两个人就不是同一部门了,这不是我想要的效果。

关键字:static - 图3

  • 改造为用static修饰department变为静态变量
    「同一个类的所有实例对象的部门归属department都是质量控制部」

静态变量将变量值存储在一个公共的内存地址。

  1. private static String department = "质量控制部";
  • 测试类中创建TestEngineer对象并使用

关键字:static - 图4

可以看到无论是怎么修改,对应的部门会一直是一个统一的

需求二
  • 想要修改 类的所有实例共享的数据,怎么解决??

公司进行部门名称改革,质量控制部改为测试部

分析
  • 在测试类中直接修改TestEngineer对象的静态变量department

因为static变量存放的是公共地址,所以如果修改了某个类的静态变量值,那该类的所有实例的静态变量都会被影响到,即都会被修改

  1. TestEngineer.setDepartment("测试部");
  • 修改了department,对应所有人的所属部门都会进行更改。

关键字:static - 图5

注意⚠️

随意修改static修饰的属性有风险,我们一般为了避免风险,会把final和static配合使用,即把静态变量变为静态常量

  1. private final static String department = "质量控制部";

关键字:static - 图6

  1. //部门名 让大家都能使用到,权限修饰符为public
  2. //常量命名规则,变量名全部大写
  3. public final static String DEPARTMENT = "质量控制部";

关键字:static - 图7

作用

  • 成员变量由对象层级提升为类层级
  • 整个类只有一份并被所有对象共享
  • static修饰的成员变量随着类的加载准备就绪,与是否创建对象无关
  1. //static修饰的成员变量随着类的加载准备就绪,与是否创建对象无关
  2. System.out.println(TestEngineer.department);
  3. System.out.println(TestEngineer.DEPARTMENT);

关键字:static - 图8

可以看到在没有创建对象之前打印对应的部门变量,也是可以打印成功的,对应的有赋值的打印赋值内容;没有赋值的就打印声明类型的默认值

关键字:static - 图9

静态方法

调用方式

  1. 类名.静态方法名(参数)

特点

静态方法「static method」的特点:

  • 不能调实例方法或访问实例数据域,因为静态方法中没有对象this关键字。
  1. public class ReverseList {
  2. int num1 = 15;
  3. static int num2 = 22;
  4. public static void reverse(){
  5. System.out.println(num1);
  6. }
  7. }

关键字:static - 图10

非静态成员必须类创建对应实例对象的时候才能进行访问,而静态方法和静态变量是不需要创建实例对象,在类初始化的时候就可以访问静态的方法和变量了。
而且类是优先于对象存在的,所以无法在静态方法里面访问非静态成员变量

  • 可以调用静态方法及访问静态数据域。
  1. public class ReverseList {
  2. int num1 = 15;
  3. static int num2 = 22;
  4. public void show(){
  5. System.out.println(num1);
  6. System.out.println(num2);
  7. }
  8. public static void show1(){
  9. //非静态变量必须是 实例化名.变量名
  10. // System.out.println(num1);//静态方法不能调用非静态变量
  11. System.out.println(num2);//静态方法可以调用静态变量
  12. }
  13. }

关键字:static - 图11

因为静态方法和静态数据域不属于某个特定的对象,只属于这个类。

被static修饰的内容就不再属于某一个对象了,而是属于类

使用场景

首先第一个场景就是只访问静态成员的时候就可以使用静态方法了,第二个场景就是不关心对象的状态,所有需要的参数都由参数列表显示提供

当想要调用一个方法的时候,想要通过类名.方法名的方式去调用,而不是实例对象名.方法名的方式去调用,就可以使用静态方法

说明

需求
  • 定义静态方法,反转数组中的元素
  1. 数组下标 0,1,2,3,4
  2. 1,3,5,7,9
  3. 转换: 9,7,5,3,1

[0]和[4]换,[1]和[3]换;下面demo先介绍下对应交换变量的业务逻辑

  1. public class ReverseListDemo {
  2. public static void main(String[] args) {
  3. //交换变量
  4. int a = 1;
  5. int b = 2;
  6. int temp = a;
  7. //temp=1,a = 1,b = 2
  8. a = b;//temp=1,a = 2,b = 2
  9. b = temp;//temp=1,a = 2,b = 1
  10. System.out.println("a:" + a);
  11. System.out.println("b:" + b);
  12. }
  13. }

分析
  • 先明确定义方法的三要素
    • 方法名: reverseList{反转数组}
    • 参数列表:int[] arrays
    • 返回值类型:void

这里只需要进行数组反转,不需要返回对象进行其它操作,所以用void当返回值

  • 明确需求
    • 遍历数组
      • 在遍历的时候交换数组对应索引 ``` arrays[i] <=> arrays[arrays.length-1-i]

[0] <=> [4]

[1] <=> [3]

  1. - `i>=(length-1-i)`时,停止交换
  2. ```java
  3. package top.testeru.keywords.staticp;
  4. /**
  5. * @Package: top.testeru.keywords.staticp
  6. * @author: testeru.top
  7. * @Description:
  8. * @date: 2022年02月15日 3:13 PM
  9. */
  10. public class ReverseList {
  11. int num1 = 15;
  12. static int num2 = 22;
  13. public void show(){
  14. System.out.println(num1);
  15. System.out.println(num2);
  16. }
  17. public static void show1(){
  18. //非静态变量必须是 实例化名.变量名
  19. // System.out.println(num1);//静态方法不能调用非静态变量
  20. System.out.println(num2);//静态方法可以调用静态变量
  21. }
  22. public static void reverse(int[] arrays){
  23. //非静态方法必须是 实例化名.方法名
  24. //show(); //静态方法不能调用非静态方法
  25. show1();//静态方法可以调用静态方法
  26. /**
  27. * 交换元素的动作就可以
  28. * 假设数组元素值为: int[] arrays = [1,2,3,4,5]
  29. * 明确交换内容:lastIndex = length-1
  30. * a b
  31. * arrays[0]=1 arrays[lastIndex]=5 交换
  32. * arrays[1]=2 arrays[lastIndex-1]=4 交换
  33. * ...
  34. * arrays[i] arrays[lastIndex-i] 交换
  35. * 明确交换次数:
  36. * length/2
  37. */
  38. for (int i = 0; i < arrays.length/2; i++) {
  39. int temp = arrays[i];
  40. int lastIndex = arrays.length-1;
  41. arrays[i] = arrays[lastIndex];
  42. arrays[lastIndex] = temp;
  43. }
  44. }
  45. }
  1. package top.testeru.keywords.staticp;
  2. /**
  3. * @Package: top.testeru.keywords.staticp
  4. * @author: testeru.top
  5. * @Description:
  6. * @date: 2022年02月15日 3:24 PM
  7. */
  8. public class ReverseListDemo {
  9. public static void main(String[] args) {
  10. int[] arrays = {1,2,3,4,5};
  11. for (int array : arrays) {
  12. System.out.print(array+",");
  13. }
  14. System.out.println("");
  15. System.out.println("-----开始数组转换-----");
  16. //开始数组转换
  17. ReverseList.reverse(arrays);
  18. for (int array : arrays) {
  19. System.out.print(array+",");
  20. }
  21. }
  22. }

关键字:static - 图12

总结

static关键字

  1. 概念

    理解就可以,知道对应的修饰内容是静态的

  2. 作用

    static的作用,可以修饰成员变量也可以修饰成员方法

  3. static修饰成员变量的特点

    也就是变量被该类下所有的对象所共享,这是需要我们掌握和会用的

  4. static修饰成员方法的特点

    这个方法可以通过类名.方法名的形式直接进行调用,并且静态方法是没有this关键字的,所以不能访问非静态成员,这个应用需要我们掌握的,至于概念大家理解就可以

  1. static用于修饰类的成员:
  2. 成员变量:静态变量、类变量「被类中的所有对象所共享」
  3. 方法:静态方法、类方法「不能访问类中的实例成员-实例数据和方法」

关键字:static - 图13

实体类中new创建的对象分配内存地址在栈区,具体的赋值内容在堆区,静态的成员变量/方法{static修饰}则被放在方法区内

类刚被加载时,所有类的信息都放在方法区