“我们来谈一个新的主题。现在,我想讨论 static 变量和方法。”
“艾莉,我已经了解 static 变量和方法了。但我想了解更多详细信息。”
“当我们在类中声明变量时,我们会定义这些变量是只创建一次,还是该类的每个实例(对象)都将有自己的副本。默认情况下,将为每个对象创建变量的一个新副本。它看起来是这样的:”
class Cat // 类
{
String name; // 变量
Cat(String name) // 构造方法
{
this.name = name; // 变量初始化
}
}
Cat cat1 = new Cat("奥斯卡"); // 创建一个 name 变量包含“奥斯卡”的对象
Cat cat2 = new Cat("米西"); // 创建一个 name 变量包含“米西”的对象
System.out.println(cat1.name);
System.out.println(cat2.name);
奥斯卡
米西
“尽管是在同一个类 (Cat) 中声明的,变量 cat1.name
和 cat2.name
却包含不同的值,因为它们引用不同的对象。”
“有道理。”
“但是,类的每个实例只能存在 static 变量的一个副本,并且必须使用类名访问该副本。”
class Cat // 类
{
String name; // 实例(非 static)变量
static int catCount; // static 变量
Cat(String name)
{
this.name = name;
Cat.catCount++; // 将 static 变量加 1
}
}
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 方法的工作原理:
代码看起来如下所示
|
实际发生的情况如下
|
使用 <对象>.<方法名称> 调用方法时,实际上是在调用类方法,并将该对象作为第一个参数进行传递。在方法内,对象称为‘this’。方法中的所有操作都是针对此对象及其数据执行的。” |
“下面是 static 方法的工作原理:
代码看起来如下所示
|
实际发生的情况如下
|
当调用 static 方法时,没有对象被传递给它。也就是说,‘this’ 相当于空值 null。这导致 static 方法无法访问非 static 变量和方法,因为它没有任何内容隐式传递给非 static 方法。” |
“如果变量或方法前面有关键字 static,则为 static。”
“既然限制如此严格,为什么需要这种方法呢?”
“嗯,这种方法自有其优点。”
“首先,我们不必传递对象引用即可使用 static 方法和变量。”
“第二,有时需要只有一个变量副本。例如,System.out(System 类的 static out 变量)。”
“第三,有时你需要先调用一个方法,然后才能创建对象。”
“艾莉,可以给我举个这样的例子吗?”
“你为什么认为 main() 方法是 static?它是 static,因此程序员可以在任意对象创建之前,在将类加载到内存后立即调用它。
GO TO FULL VERSION