变量是什么
变量是一个有名字的盒子,里面装着一个值。在 Java 中,每个变量都有一个固定的类型,在声明时就确定下来,之后永远不会改变。这就是 Java 被称为静态类型语言的原因:编译器在程序运行之前就知道每个变量的类型,如果代码把错误类型的值放进盒子里,它会拒绝编译。
一个声明由三部分组成:类型、名字,以及(通常还有)一个初始值。
int age = 30; 可以读作“创建一个名为 age 的 int,把 30 放进去”。分号结束这条语句,正如注释那一页所说,每条语句都以分号结尾。
先声明,后赋值
你可以把声明和第一次赋值分开。类型只在声明时写一次;之后赋值时只需要写名字和 =:
有一条规则常让新手栽跟头:你必须在读取局部变量之前给它赋值。编译器会跟踪这一点,并拒绝读取未初始化局部变量的代码:
int score;
System.out.println(score); // compile error: variable score might not have been initialized
这是一项功能,而不是麻烦:它能在程序运行之前就揪出一整类 bug。
命名规则与规范
Java 强制执行几条硬性规则,在此之上还有一些约定俗成的规范。规则是:名字可以包含字母、数字、_ 和 $,但不能以数字开头,不能是保留关键字(比如 int 或 class),而且区分大小写(age 和 Age 是两个不同的变量)。
大家都遵守的规范:
- 变量和方法使用
camelCase:firstName、totalScore。 - 常量使用
UPPER_SNAKE_CASE:MAX_USERS。 - 名字应该描述它的值:用
count,而不是c;用userEmail,而不是x。
清晰的名字不是装饰,而是未来的你读懂代码的方式。totalPrice = itemCount * pricePerItem 一看就懂,而 t = c * p 永远做不到这一点。
类型安全:盒子保持它的类型
因为类型在声明时就被锁定,你不能把错误类型的值放进变量里。这能在编译时就发现错误:
int age = 30;
age = "thirty"; // compile error: incompatible types - String cannot become int
在不同数字类型之间赋值时,遵循拓宽规则:较小的类型会自动转换成较大的类型,反过来则不行。我们会在数据类型和类型转换两页中详细讲解;现在只需要知道,编译器一直在盯着。
var 关键字
从 Java 10 开始,你可以用 var 代替类型,让编译器根据右边的值推断出类型:
var 不是动态类型:name 和你写成 String name 时一样,就是一个 String,之后你依然不能把 int 赋给它。它只是让你少打几个字。需要注意的是:var 需要一个初始值来推断类型,所以 var x; 是不合法的;而且它只能用于局部变量,不能用于字段、方法参数或返回类型。当右边的值已经清楚表明类型时就用它;写出类型能让代码更清晰时,就把类型写出来。
用 final 定义常量
如果一个值设定之后就不应该再改变,就把它标记为 final。任何重新赋值的尝试都会变成编译错误:
final 表明了你的意图(“这是一个固定值”),并让编译器替你守护它。只要一个值在概念上是常量,比如费率、上限、配置键,就用 final,这样意外的重新赋值会被及时发现,而不是悄悄地带着 bug 上线。
变量作用域
变量只存在于声明它的代码块(也就是 { ... })内部,到右花括号就会消失。这就是它的作用域。在 for 循环或 if 代码块内部声明的变量,在外面是看不见的:
i 和 square 都属于循环,循环结束时就消失了;total 声明在外层代码块中,所以它还在。实用的结论是:在需要它的最小代码块里声明每个变量。作用域越小,争夺你注意力的名字就越少,在远离赋值的地方误用某个值的机会也越少。
下一页:数据类型
这一页的每个变量都以一个类型开头:int、double、String、boolean。下一页将详细拆解 Java 的数据类型:八种基本类型、每种类型占多大空间、基本类型和对象的区别,以及什么时候该用哪种类型。
常见问题
Java 中如何声明变量?
先写类型,再写名字,然后可以选择赋一个值:int age = 30;。类型(int)在变量的整个生命周期内固定不变;名字(age)是你引用它的方式。你也可以把声明和赋值分开写,int age; age = 30;,但在读取局部变量之前必须先给它赋值。
Java 中的 var 关键字是什么?
从 Java 10 开始,var 让编译器根据你赋的值推断局部变量的类型:var name = "Ada"; 会让 name 成为 String。它仍然是静态类型:类型在编译时就已确定,并不是动态的。var 只能用于带初始值的局部变量,不能用于字段、参数或未初始化的声明。
Java 中如何定义常量?
加上 final 关键字:final double PI = 3.14159;。final 变量一旦赋值就不能再重新赋值,编译器会拒绝任何这样的尝试。按照惯例,常量用 UPPER_SNAKE_CASE 书写,以便和普通变量区分开。