“我们来谈一个新的主题。现在,我想讨论 static 变量和方法。”

“艾莉,我已经了解 static 变量和方法了。但我想了解更多详细信息。”

“当我们在类中声明变量时,我们会定义这些变量是只创建一次,还是该类的每个实例(对象)都将有自己的副本。默认情况下,将为每个对象创建变量的一个新副本。它看起来是这样的:”

类声明
class Cat                        // 类
{
    String name;                 // 变量

    Cat(String name)             // 构造方法
    {
        this.name = name;        // 变量初始化
    }
}
main 方法中的代码:
Cat cat1 = new Cat("奥斯卡"); // 创建一个 name 变量包含“奥斯卡”的对象
Cat cat2 = new Cat("米西"); // 创建一个 name 变量包含“米西”的对象
System.out.println(cat1.name);
System.out.println(cat2.name);
屏幕输出信息
奥斯卡
米西

“尽管是在同一个类 (Cat) 中声明的,变量 cat1.namecat2.name 却包含不同的值,因为它们引用不同的对象。”
“有道理。”
“但是,类的每个实例只能存在 static 变量的一个副本,并且必须使用类名访问该副本。”

类声明
class Cat                   // 类
{
    String name;            // 实例(非 static)变量
    static int catCount;    // static 变量

    Cat(String name)
    {
        this.name = name;
        Cat.catCount++;   // 将 static 变量加 1
    }
}
main 方法中的代码:
System.out.println(Cat.catCount);
Cat cat1 = new Cat("奥斯卡");

System.out.println(Cat.catCount);
Cat cat2 = new Cat("米西");

System.out.println(cat1.name);
System.out.println(cat2.name);
System.out.println(Cat.catCount);
屏幕输出:
 0
1
奥斯卡
米西
2

“嗯,也很有道理。”

“Java 方法分为两个类别。实例方法是在对象上调用的,并且可以访问该对象的数据。static 方法没有该访问权限,因为它们根本没有对象引用。但是,它们可以引用类的 static 变量和其他 static 方法。

static 方法无法处理非 static 方法或非 static 变量!”

“为什么呢,艾莉?”

“每个实例变量都包含在一个对象中。只有当你具有对该对象的引用时,才可以访问它。static 方法没有此类引用。”

“实例方法有这种引用吗?”

“是的,它被间接传递给实例方法。对调用实例方法的对象的引用被间接传递给该实例方法。存储此引用的变量称为 this。this 使得方法始终可以访问对象的数据或调用同一对象上的另一个非 static 方法。

将 null(而不是对象引用)传递给 static 方法。这就是它们不能处理非 static 变量和方法的原因。它们根本没有对与这些变量和方法相关联的对象的引用。”

“好的,艾莉,我明白了。”

“以下是非 static 方法的工作原理:

代码看起来如下所示
Cat cat = new Cat();
String name = cat.getName();
cat.setAge(17);
cat.setChildren(cat1, cat2, cat3);
实际发生的情况如下
Cat cat = new Cat();
String name = Cat.getName(cat);
Cat.setAge(cat, 17);
Cat.setChildren(cat, cat1, cat2, cat3);
使用 <对象>.<方法名称> 调用方法时,实际上是在调用类方法,并将该对象作为第一个参数进行传递。在方法内,对象称为‘this’。方法中的所有操作都是针对此对象及其数据执行的。”

“下面是 static 方法的工作原理:

代码看起来如下所示
Cat cat1 = new Cat();
Cat cat2 = new Cat();
int catCount = Cat.getAllCatsCount();
实际发生的情况如下
Cat cat1 = new Cat();
Cat cat2 = new Cat();
int catCount = Cat.getAllCatsCount(null);
当调用 static 方法时,没有对象被传递给它。也就是说,‘this’ 相当于空值 null。这导致 static 方法无法访问非 static 变量和方法,因为它没有任何内容隐式传递给非 static 方法。”

“如果变量或方法前面有关键字 static,则为 static。”

“既然限制如此严格,为什么需要这种方法呢?”

“嗯,这种方法自有其优点。”

“首先,我们不必传递对象引用即可使用 static 方法和变量。

“第二,有时需要只有一个变量副本。例如,System.out(System 类的 static out 变量)。”

“第三,有时你需要先调用一个方法,然后才能创建对象。”

“艾莉,可以给我举个这样的例子吗?”

“你为什么认为 main() 方法是 static?它是 static,因此程序员可以在任意对象创建之前,在将类加载到内存后立即调用它。