美文网首页
63. Java 类和对象 - static 关键字

63. Java 类和对象 - static 关键字

作者: Cache技术分享 | 来源:发表于2025-04-29 09:26 被阅读0次

63. Java 类和对象 - static 关键字

了解类成员:static 关键字

在 Java 中,static 关键字用于修饰字段和方法,使其成为类级别的成员,而非对象级别的成员。也就是说,被声明为 static 的成员与类本身绑定,无论创建多少个对象,它们都只有一份拷贝。这种特性使得 static 成为实现全局共享数据、工具方法以及常量的重要手段。


1. 类变量(static 字段)

1.1 与实例变量的区别

  • 实例变量
    • 每个对象都有独立的实例变量副本,存储在各自的内存中。
    • 修改某个对象的实例变量只影响该对象,不会对其他对象产生影响。
  • 类变量(static 字段)
    • 整个类中只有一份存储空间,所有对象共享同一份数据。
    • 不管创建多少个该类的实例,类变量都只有一个,并且可以通过类名直接访问。

1.2 用法示例

下面的示例展示了如何使用 static 字段记录所有 Bicycle 对象的创建数量,同时为每个对象分配独一无二的 ID:

public class Bicycle {
    // 实例变量,每个对象各自拥有
    private int cadence;
    private int gear;
    private int speed;
    private int id;  

    // 类变量:所有 Bicycle 实例共享,记录创建的数量
    private static int numberOfBicycles = 0;

    public Bicycle(int startCadence, int startSpeed, int startGear) {
        this.cadence = startCadence;
        this.speed = startSpeed;
        this.gear = startGear;

        // 每创建一个新对象,计数加 1,并将计数赋值给该对象的 id
        id = ++numberOfBicycles;
    }
    
    public int getID() {
        return id;
    }
}
public static void main(String[] args) {
    Bicycle bike1 = new Bicycle(3, 100, 50);
    System.out.println(bike1.id);
    Bicycle bike2 = new Bicycle(2, 80, 40);
    System.out.println(bike2.id);
}

在这个示例中:

  • numberOfBicyclesstatic 字段,记录了创建的 Bicycle 数量,全类仅有一份,所有实例共享该数据。
  • 每个 Bicycle 对象都有自己的实例变量 id,用来区分不同对象。

1.3 访问类变量

  • 推荐方式:使用 类名.类变量名 访问,例如:Bicycle.numberOfBicycles。这种方式能清晰地表明该变量是属于类的。
  • 不推荐方式:通过对象引用访问,如 myBicycle.numberOfBicycles。这种方式容易让人误解为该变量是对象的专属属性,而非全局共享的。
System.out.println( Bicycle.numberOfBicycles);
System.out.println( bike1.numberOfBicycles);
System.out.println( bike2.numberOfBicycles);

2. 类方法(static 方法)

2.1 与实例方法的区别

  • 实例方法
    • 属于对象,必须先创建对象后才能调用。
    • 调用方式:对象名.方法名()
  • 类方法(static 方法)
    • 属于类本身,可以直接通过 类名.方法名() 调用。
    • 不依赖任何具体的对象实例。

2.2 用法示例

假设我们想获取当前创建的 Bicycle 数量,可以通过以下 static 方法实现:

public class Bicycle {
    // ...(其他成员同上)

    // 类方法:无需对象即可调用,用于获取创建的 Bicycle 数量
    public static int getNumberOfBicycles() {
        return numberOfBicycles;
    }
}

调用时只需使用:

int total = Bicycle.getNumberOfBicycles();

这样既直观又方便,无需先实例化对象。

2.3 注意事项:不能直接访问实例成员

由于 static 方法不属于任何具体对象,因此在方法体内无法直接使用实例变量或 this 关键字。例如:

public static void foo() {
    // 编译错误:不能使用 this 或直接访问实例变量
    // System.out.println(this.cadence);  
}

如果需要访问实例数据,必须通过已有对象引用来访问:

public static void printBicycleSpeed(Bicycle bicycle) {
    System.out.println("Speed: " + bicycle.speed);
}

3. 常量(static final)

在 Java 中,使用 static final 修饰的变量被称为常量,其值在程序运行过程中不能改变。这些常量通常在类加载时就被初始化,并且全类共享。

3.1 示例

public class MathConstants {
    public static final double PI = 3.141592653589793;
    public static final int MAX_VALUE = 100;
}
  • final 表示常量一经赋值就不能再修改。
  • static 表示常量是全类共享的,无需创建对象即可访问。
  • 常量命名通常使用全大写字母,并用下划线 _ 分隔单词,例如 MAX_SPEEDDEFAULT_CAPACITY

3.2 编译时常量

当常量的值在编译时已知(如上述 PI),编译器可能会将代码中所有对该常量的引用直接替换为实际值,这样在性能上会更高效。但这也意味着若常量值修改,所有引用该常量的类都需要重新编译。


4. 使用 static 的注意事项与最佳实践

  1. 数据共享与全局状态
    • 使用 static 字段可以方便地实现数据共享,例如计数器或全局配置信息。
    • 过度依赖 static 变量可能导致代码间的耦合度增加,从而使单元测试和维护变得困难。
  2. 工具方法与辅助函数
    • 很多工具类(如 java.lang.Math)中的方法都是 static 的,因为这些方法不依赖对象状态,只提供通用功能。
  3. 线程安全
    • 在多线程环境下使用 static 字段时要注意同步问题,因为多个线程可能同时访问和修改共享数据。
  4. 避免误用
    • 切记不要滥用 static。在设计时应仔细考虑某个方法或字段是否确实不依赖于对象状态,只有在确定其为全局共享的情况下再使用 static

5. 综合示例

以下示例整合了类变量、类方法、实例变量及常量的用法,展示了如何设计一个既能统计对象数量,又能提供工具方法的类:

public class Bicycle {
    // 实例变量,每个对象独有
    private int cadence;
    private int gear;
    private int speed;
    private int id;  

    // 类变量:所有 Bicycle 实例共享
    private static int numberOfBicycles = 0;
    
    // 类常量:不变的最大速度限制
    public static final int MAX_SPEED = 50;

    public Bicycle(int startCadence, int startSpeed, int startGear) {
        this.cadence = startCadence;
        this.speed = startSpeed;
        this.gear = startGear;
        // 对象计数自增
        id = ++numberOfBicycles;
    }
    
    public int getID() {
        return id;
    }
    
    // 类方法:返回已创建的 Bicycle 对象总数
    public static int getNumberOfBicycles() {
        return numberOfBicycles;
    }
    
    // 工具方法:判断给定速度是否超过最大速度限制
    public static boolean isSpeedLegal(int speed) {
        return speed <= MAX_SPEED;
    }
    
    // 实例方法:调整当前对象的速度
    public void changeSpeed(int delta) {
        int newSpeed = speed + delta;
        if (isSpeedLegal(newSpeed)) {
            speed = newSpeed;
        } else {
            System.out.println("超出允许的最大速度!");
        }
    }
}

在这个综合示例中:

  • 使用 static 字段统计创建的 Bicycle 数量。
  • 通过 static 方法获取对象数量或判断速度是否合法。
  • 使用 static final 常量 MAX_SPEED 限制最大速度。
  • 实例方法 changeSpeed 则根据对象当前状态进行操作,并利用工具方法进行判断。

相关文章

  • 十四: Java中的static

    Java中的static 在我们接触对象类之前,我们写的类变量和方法都是有static关键字的,不相信吗?让我们来...

  • Java 面向对象2

    Java 面向对象 1. static 和 final static关键字---修饰成员变量 用static修饰的...

  • 第31节:Java基础-类与对象

    前言 Java基础-类与对象,方法的重载,构造方法的重载,static关键字,main()方法,this关键字,包...

  • Java的static、final关键字

    一、 static关键字 可以修饰成员变量和成员方法 static关键字特点随着类的加载而加载优先于对象存在被类的...

  • 【Java】关键字

    一、 static关键字 static关键字的总结: static关键字 可以再没有创建对象的时候进行调用类的元素...

  • Kotlin Vocabulary | 唯一的 "对象"

    在 Java 语言中,static 关键字主要用于表明方法和属性是属于某个对象,而不是属于对象的实例。static...

  • essential scala: 伴生对象

    essential scala: 伴生对象 有时候我们想创建属于类的方法,在java中使用static关键字. 在...

  • 新学的java知识,静态类,使用static关键字修饰的类(pu

    新学的java知识,静态类,使用static关键字修饰的类(public static class) 今天在看别人...

  • static 关键字

    static 关键字意义:方便在没有创建对象的清了下调用方法和变量static 可以用来修饰类的成员方法、类的成员...

  • 类和对象

    类和对象的定义、关系 成员方法:去掉static关键字的方法 单个对象内存图 多个对象的内存图 成员变量:类中方法...

网友评论

      本文标题:63. Java 类和对象 - static 关键字

      本文链接:https://www.haomeiwen.com/subject/fsnxijtx.html