变量简介
通过本课提供的示例,深入理解变量的概念以及变量声明对Java程序的影响。
在本节课中,我们将讨论不同类型的变量和数据类型。其中包括作为新创建对象的引用变量,它充当指向该对象的句柄。在设计和编写对象状态时,我们应该遵循一些规则和约定。除了 int 或 boolean 之外,还有其他数据类型;此外,我们还应清楚地了解如何为变量赋值。如果我们没有显式初始化它们,它们是否会被赋予默认值?让我们通过示例来学习所有这些技术。
编码示例:14
在此示例中,我们将探讨 Java 的核心概念。我们知道,局部变量的值存储在“栈”中,而新创建的对象则存储在“堆”中。然而,作为对象句柄的引用变量存储在“栈”中,它仅指向新对象。
让我们先看代码示例,然后讨论实际发生了什么。
1class ReferenceVariable { 2 int num; 3} 4 5public class ExampleFourteen { 6 public static void main(String[] args) { 7 int i = 10; 8 int j = 5; 9 System.out.println(i + " " + j); 10 i = j; 11 System.out.println(i + " " + j); 12 j++; 13 System.out.println(i + " " + j); 14 15 ReferenceVariable numOne = new ReferenceVariable(); 16 ReferenceVariable numTwo = new ReferenceVariable(); 17 numOne = numTwo; 18 numOne.num = 10; 19 System.out.println(numOne.num + " " + numTwo.num); 20 numTwo.num++; 21 System.out.println(numOne.num + " " + numTwo.num); 22 } 23}
代码说明
如您在上述代码中所见,有两个局部变量 int i 和 int j。我们首先输出了两个值。接着,在第 10 行执行 i = j,并在第 12 行将 j 的值加 1。实际上,这个值的变化应该反映到 i 上。然而,j 值的变化并未影响 i 的值。
在程序的第二部分,我们处理了两个对象。请看代码中的这几行:
1ReferenceVariable numOne = new ReferenceVariable(); 2ReferenceVariable numTwo = new ReferenceVariable(); 3numOne = numTwo;
在上述代码中,numOne 和 numTwo 是两个引用变量,分别指向在“堆”中创建的两个新对象。相比之下,这两个引用变量本身存储在“栈”中。当我们让它们相等后,第一个引用变量 numOne 现在指向第二个对象,不再反映第一个对象的值。
如果您仔细观察输出结果,会发现“传值调用”与“传引用调用”的区别。
在第一种情况下,j 后续的变化并没有影响到 i;但在第二种情况下,numOne 获得了 numTwo 的值。在第二种情况中,引用变量 numOne 作为第一个对象的句柄,被撤销并指向第二个对象。
编码示例:15
在接下来的两个编码示例中,我们将了解不同类型的变量。我们该如何使用局部变量?
1public class ExampleFifteen { 2 // 局部变量 3 public void WeightOfFatherBear() { 4 int weight = 0; 5 weight = 180; 6 System.out.println("父亲熊的体重是:" + weight); 7 } 8 9 public static void main(String[] args) { 10 ExampleFifteen fatherWeight = new ExampleFifteen(); 11 fatherWeight.WeightOfFatherBear(); 12 } 13}
代码说明
这是一个非常简单的程序。但它提醒我们一个关键点:不能在作用域之外使用局部变量。
编码示例:16
让我们来看一下这个编码示例。
1public class ExampleSixteen { 2 // 在作用域外使用局部变量 3 public void WeightOfChildBear() { 4 int weight = 0; 5 weight = 80; 6 } 7 8 public static void main(String[] args) { 9 // 这将导致错误 10 System.out.println("小熊的体重是:" + weight); 11 } 12}
代码说明
这会产生错误。
当局部变量在方法内部声明时,只能在该方法内使用。虽然可以稍后调用该方法,但若要修复此代码,可将第 4 行的语句移出函数,并添加如下内容:
1static int weight = 100;
编码示例:17
在本示例中,我们将发现另一个关键点:局部变量必须被初始化,否则会引发错误。
1/* 2局部变量必须被初始化 3*/ 4 5public class ExampleSeventeen { 6 7 // 局部变量 8 public void WeightOfMotherBear() { 9 int weight; 10 System.out.println("母熊的体重是:" + weight); 11 } 12 13 public static void main(String[] args) { 14 ExampleSeventeen motherBear = new ExampleSeventeen(); 15 // 你不能在这里初始化局部变量 16 // 这将导致错误 17 motherBear.weight = 150; 18 motherBear.WeightOfMotherBear(); 19 } 20}
代码说明
我们应当更早地对变量进行初始化。相反,我们尝试通过对象引用赋值,这是无效的。您可以通过修改第 17 行来修复错误:
1// motherBear.weight = 150;
另一方面,类级别的实例变量不需要初始化,因为编译器会为它们赋予默认值(int 为 0,对象引用为 null)。您可以在第 9 行添加以下代码来修复错误:
1int weight = 150;
编码示例:18
让我们来看一个编码示例。
1import java.io.*; 2 3// 这些是实例变量 4// 无需像局部变量那样进行初始化 5class StudentClasses { 6 int className; 7 // 我们还可以添加更多状态和方法来改变状态 8} 9 10public class ExampleEighteen { 11 public static void main(String args[]) { 12 // 此处 john 是引用变量 13 // 它将作为新对象的句柄 14 // john 存储在栈中,新对象存储在堆中 15 StudentClasses john = new StudentClasses(); 16 // 现在 john 可以访问实例变量 17 john.className = 1; 18 System.out.println("新学生 john 就读于班级:" + john.className); 19 StudentClasses mary = new StudentClasses(); 20 mary.className = 2; 21 System.out.println("新学生 mary 就读于班级:" + mary.className); 22 john.className = mary.className; 23 System.out.println("一年后,john 通过考试,现在就读于:" + john.className); 24 } 25}
代码说明
此代码不会产生之前示例中的错误。className 实例变量分别独立地属于每个 student 类对象。