1. 变量:程序世界的数据容器
在Java编程中,变量是最基础也是最重要的概念之一。简单来说,变量就是内存中存储数据的一个命名空间。想象一下你家里的储物柜——每个抽屉都有不同的用途,有的放餐具,有的放文件。变量就是程序中的"抽屉",用来分类存放各种数据。
1.1 变量的本质与内存机制
当我们在Java中声明一个变量时,实际上是在做三件事:
- 向内存申请一块存储空间
- 给这个空间取个有意义的名字(变量名)
- 指定这个空间能存放什么类型的数据(数据类型)
计算机内存会被划分成许多小单元,每个单元都有唯一的地址,就像酒店的房间号。但记住"0x7ffee3a4c8a0"这样的地址对人类来说太困难了,所以我们用变量名这个别名来指代内存位置。
重要提示:Java是强类型语言,这意味着每个变量都必须先声明其数据类型,然后才能使用。这种设计虽然看起来麻烦,但能帮助我们在编码阶段就发现很多潜在的类型错误。
1.2 变量命名规范详解
良好的命名习惯是优秀程序员的基本素养。Java变量命名遵循以下规则:
-
组成字符:字母、数字、下划线(_)和美元符号($)
- 合法示例:age, _count, $value, user1
- 非法示例:user-name, 2things, @email
-
开头限制:不能以数字开头
- 合法:count2
- 非法:2count
-
关键字避让:不能使用Java保留字
- 非法:int, class, public等约50个关键字
-
大小写敏感:name和Name是两个不同变量
-
命名风格:
- 单个单词:全部小写(age)
- 多个单词:小驼峰式(userName)
- 常量:全部大写,下划线分隔(MAX_SIZE)
-
语义化原则:变量名应清晰表达其用途
- 好的命名:studentCount, totalPrice
- 差的命名:a, x1, temp
1.3 Java的八大基本数据类型
Java将数据分为基本类型和引用类型。基本类型是构建程序的基础砖块,共有8种:
| 数据类型 | 大小(位) | 取值范围 | 默认值 | 说明 |
|---|---|---|---|---|
| byte | 8 | -128~127 | 0 | 最小整数类型 |
| short | 16 | -32768~32767 | 0 | 短整数 |
| int | 32 | -2³¹~2³¹-1 | 0 | 最常用的整数类型 |
| long | 64 | -2⁶³~2⁶³-1 | 0L | 大范围整数 |
| float | 32 | ±3.4E38 | 0.0f | 单精度浮点数 |
| double | 64 | ±1.7E308 | 0.0 | 双精度浮点数 |
| char | 16 | '\u0000'~'\uffff' | '\u0000' | 单个Unicode字符 |
| boolean | 1 | true/false | false | 布尔值 |
实际开发中最常用的组合是:
- 整数:int
- 大整数:long
- 小数:double
- 布尔:boolean
- 字符:char
java复制// 基本数据类型声明示例
int age = 25; // 最常用的整数类型
double price = 19.99; // 默认的小数类型
boolean isActive = true; // 只有true/false两种值
char grade = 'A'; // 单引号包裹单个字符
1.4 变量声明与使用的三种方式
Java中变量的使用通常遵循"声明->赋值->使用"的流程:
- 先声明后赋值
java复制int count; // 声明
count = 10; // 赋值
System.out.println(count); // 使用
- 声明同时赋值(推荐)
java复制double price = 29.99; // 声明并赋值
- 多变量声明
java复制int x = 1, y = 2, z = 3; // 同时声明多个同类型变量
经验之谈:尽量在声明时就初始化变量,避免使用未初始化的变量。Java局部变量不会自动初始化,使用未赋值的局部变量会导致编译错误。
2. 数据的输入与Scanner类
2.1 静态数据与动态输入
之前的例子都是将数据直接写在代码中(静态数据)。但在实际应用中,我们经常需要从用户那里获取输入(动态数据)。Java提供了Scanner类来实现这个功能。
2.2 Scanner使用四步曲
- 导入Scanner类
java复制import java.util.Scanner; // 必须放在文件顶部
- 创建Scanner对象
java复制Scanner scanner = new Scanner(System.in); // System.in表示标准输入(键盘)
- 读取不同类型的数据
java复制System.out.print("请输入您的年龄:");
int age = scanner.nextInt(); // 读取整数
System.out.print("请输入您的姓名:");
String name = scanner.next(); // 读取字符串(直到遇到空格/回车)
System.out.print("请输入您的身高(m):");
double height = scanner.nextDouble(); // 读取双精度浮点数
- 关闭Scanner(重要!)
java复制scanner.close(); // 释放系统资源
2.3 Scanner的常见方法
| 方法 | 返回类型 | 说明 |
|---|---|---|
| next() | String | 读取下一个单词(空格分隔) |
| nextLine() | String | 读取整行(包括空格) |
| nextInt() | int | 读取整数 |
| nextDouble() | double | 读取双精度浮点数 |
| nextBoolean() | boolean | 读取布尔值 |
常见陷阱:nextInt()/nextDouble()后接nextLine()会读取到空行。这是因为nextInt()只读取数字部分,而把回车留给了后面的nextLine()。解决方法是在中间加一个额外的nextLine()消耗掉回车。
java复制Scanner scanner = new Scanner(System.in);
System.out.print("输入年龄:");
int age = scanner.nextInt();
scanner.nextLine(); // 消耗掉剩余的行
System.out.print("输入姓名:");
String name = scanner.nextLine();
3. 常量:不可变的量
3.1 常量的定义与特性
常量是一种特殊的变量,其值一旦设定就不能更改。在Java中使用final关键字定义常量:
java复制final double PI = 3.1415926;
final int MAX_USERS = 1000;
常量的特点:
- 必须用final修饰
- 命名通常全大写,单词间用下划线连接
- 建议在声明时就初始化
- 一旦赋值后就不能再修改
3.2 常量的使用场景
- 数学常数
java复制final double PI = 3.14159;
final double E = 2.71828;
- 配置参数
java复制final int MAX_RETRY_TIMES = 3;
final int TIMEOUT = 5000; // 毫秒
- 业务常量
java复制final String DEFAULT_COUNTRY = "China";
final double TAX_RATE = 0.13;
最佳实践:将程序中不会改变的值定义为常量,可以提高代码可读性和可维护性。魔法数字(直接出现在代码中的数字)应该尽量避免,用有意义的常量名替代。
4. Java运算符全解析
4.1 赋值运算符
最基本的赋值运算符是=,它将右侧的值赋给左侧的变量:
java复制int x = 10; // 将10赋值给x
Java还提供复合赋值运算符,将运算和赋值合并:
java复制int a = 5;
a += 3; // 等价于 a = a + 3 → 8
a -= 2; // a = a - 2 → 6
a *= 4; // a = a * 4 → 24
a /= 3; // a = a / 3 → 8
a %= 5; // a = a % 5 → 3
4.2 算术运算符
Java支持标准的算术运算:
java复制int a = 10, b = 3;
System.out.println(a + b); // 13 → 加法
System.out.println(a - b); // 7 → 减法
System.out.println(a * b); // 30 → 乘法
System.out.println(a / b); // 3 → 整数除法(舍去小数)
System.out.println(a % b); // 1 → 取模(余数)
特别注意:
- 整数除法会截断小数部分
- 取模运算结果的符号与被除数相同
java复制System.out.println(10 / 4); // 2
System.out.println(10.0 / 4); // 2.5
System.out.println(-10 % 3); // -1
System.out.println(10 % -3); // 1
4.3 自增/自减运算符
++和--运算符用于对变量进行加1或减1操作:
java复制int x = 5;
x++; // x = x + 1 → 6
x--; // x = x - 1 → 5
它们可以放在变量前(前缀)或后(后缀),位置不同会影响表达式的值:
java复制int a = 5;
int b = a++; // 先用a的值(5)赋给b,然后a自增 → b=5, a=6
int c = 5;
int d = ++c; // 先c自增,然后用新值(6)赋给d → d=6, c=6
4.4 关系运算符
关系运算符用于比较两个值,返回布尔结果:
| 运算符 | 描述 | 示例 | 结果 |
|---|---|---|---|
| == | 等于 | 5 == 3 | false |
| != | 不等于 | 5 != 3 | true |
| > | 大于 | 5 > 3 | true |
| < | 小于 | 5 < 3 | false |
| >= | 大于等于 | 5 >= 5 | true |
| <= | 小于等于 | 5 <= 4 | false |
特别注意:
==比较的是值(基本类型)或引用(对象类型)- 比较字符串内容应该使用equals()方法
java复制String s1 = "hello";
String s2 = new String("hello");
System.out.println(s1 == s2); // false → 比较引用
System.out.println(s1.equals(s2)); // true → 比较内容
4.5 逻辑运算符
逻辑运算符用于组合布尔表达式:
| 运算符 | 描述 | 示例 | 结果 |
|---|---|---|---|
| && | 与 | true && false | false |
| || | 或 | true || false | true |
| ! | 非 | !true | false |
短路特性:
&&:左边为false时,右边不计算||:左边为true时,右边不计算
java复制int x = 5;
boolean result = (x > 0) && (x++ < 10); // x会自增
System.out.println(x); // 6
int y = 5;
boolean result2 = (y > 10) && (y++ < 15); // 右边不执行
System.out.println(y); // 5
4.6 条件运算符(三元运算符)
语法:条件 ? 表达式1 : 表达式2
执行逻辑:
- 条件为true → 返回表达式1的值
- 条件为false → 返回表达式2的值
java复制int a = 10, b = 20;
int max = (a > b) ? a : b; // 返回较大的值
可以嵌套使用,但不宜过度复杂:
java复制int score = 85;
String grade = (score >= 90) ? "A" :
(score >= 80) ? "B" :
(score >= 70) ? "C" : "D";
5. 类型转换与运算规则
5.1 自动类型转换(隐式转换)
当小范围类型赋值给大范围类型时,Java会自动转换:
java复制int i = 100;
long l = i; // int → long (自动)
double d = l; // long → double (自动)
转换方向:byte → short → int → long → float → double
5.2 强制类型转换(显式转换)
大范围转小范围需要强制转换,可能丢失精度:
java复制double d = 100.04;
long l = (long)d; // 100 → 丢失小数部分
int i = (int)l; // 100
风险提示:强制转换可能导致数据溢出或精度丢失,特别是在浮点数转整数时,小数部分会被直接截断而非四舍五入。
5.3 运算时的类型提升
当不同类型的数据一起运算时,Java会自动将较小的类型提升为较大的类型:
java复制int a = 5;
double b = 6.2;
double result = a + b; // a被提升为double
6. 常见问题与调试技巧
6.1 变量使用常见错误
- 未初始化变量
java复制int x;
System.out.println(x); // 编译错误
- 作用域问题
java复制{
int y = 10;
}
System.out.println(y); // 错误:y已超出作用域
- 重复定义
java复制int z = 5;
int z = 10; // 错误:重复定义
6.2 运算符优先级
当表达式中有多个运算符时,按照优先级顺序计算:
| 优先级 | 运算符 |
|---|---|
| 高 | () [] . |
| ! ~ ++ -- +(正) -(负) | |
| * / % | |
| + - | |
| << >> >>> | |
| < <= > >= instanceof | |
| == != | |
| & | |
| ^ | |
| | | |
| && | |
| || | |
| ?: | |
| 低 | = += -= *= /= %= &= ^= |= <<= >>= |
不确定时使用括号明确优先级:
java复制int result = (a + b) * c; // 明确先加后乘
6.3 调试技巧
- 使用打印语句调试
java复制System.out.println("x = " + x); // 查看变量值
- 分步验证复杂表达式
java复制// 原表达式
int result = (a++ * 2) + (--b / 3);
// 分解为
int part1 = a++ * 2;
int part2 = --b / 3;
int result = part1 + part2;
System.out.println("part1=" + part1 + ", part2=" + part2);
- 使用IDE的调试功能
- 设置断点
- 单步执行
- 查看变量值
7. 综合应用实例
7.1 计算BMI指数
java复制import java.util.Scanner;
public class BMICalculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入您的体重(kg):");
double weight = scanner.nextDouble();
System.out.print("请输入您的身高(m):");
double height = scanner.nextDouble();
double bmi = weight / (height * height);
System.out.printf("您的BMI指数是:%.2f\n", bmi);
String status = (bmi < 18.5) ? "偏瘦" :
(bmi < 24) ? "正常" :
(bmi < 28) ? "偏胖" : "肥胖";
System.out.println("体重状态:" + status);
scanner.close();
}
}
7.2 简易计算器
java复制import java.util.Scanner;
public class SimpleCalculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("输入第一个数字:");
double num1 = scanner.nextDouble();
System.out.print("输入运算符(+-*/%):");
char operator = scanner.next().charAt(0);
System.out.print("输入第二个数字:");
double num2 = scanner.nextDouble();
double result;
switch(operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num1 / num2;
break;
case '%':
result = num1 % num2;
break;
default:
System.out.println("无效运算符");
return;
}
System.out.printf("%.2f %c %.2f = %.2f\n", num1, operator, num2, result);
scanner.close();
}
}
掌握这些基础知识后,你已经具备了用Java进行基本数据处理和运算的能力。变量和运算符是构建更复杂程序的基石,建议通过大量练习来巩固这些概念。在实际开发中,良好的变量命名习惯和对数据类型的正确选择,将显著提高代码质量和可维护性。