← 返回 Java 后端知识路线
阶段 01Java 基础

类型、运算与输入:把外部文字变成可计算的数据

从变量声明、八种基本类型和运算符开始,再用 Scanner 完成第一个真正由用户输入驱动的小程序。

第 02 / 35 篇
变量基本类型运算符Scanner

先看这一课值不值得学

学完后,你手里多了哪些代码积木

把键盘文字转换成能参与计算和判断的值。

本课正式新增

语法 / API / 命令你必须会到什么程度
int age = 20;声明变量、指定类型并赋初值
+ - * / %算术运算;整数除法和取余要能手算
> >= < <= == !=比较后得到 boolean 结果
&& || !组合多个真假条件,得到 boolean 结果
new Scanner(System.in)创建键盘输入对象,再调用 nextLine/nextInt
(int) value显式类型转换;可能损失精度

本课只借用,先别硬背

  • BigDecimal 留到第 8 课学习金额,不作为本课门槛
  • Spring MVC 参数绑定只用于说明项目去向,留到第 21—26 课正式学习

学完必须能独立写

  • 读取商品名、单价和数量并计算小计
  • 解释字符串拼接、整数除法和 Scanner 输入换行问题
本课目录
  1. 1. 现实问题:为什么输入的 2 有时会变成 23
  2. 2. 最小可运行示例:先让输入真正参与计算
  3. 3. 语法拆解:变量、八种基本类型和表达式
  4. 算术、比较和逻辑运算
  5. + 为什么一会儿相加、一会儿拼接
  6. 4. Scanner 调用链:键盘字符怎样进入变量
  7. 5. 为什么这样设计:类型是编译器替你守住的边界
  8. 6. 项目落点:今天的控制台输入以后会变成 HTTP 参数
  9. 7. 易错排查与动手练习
  10. 8. 一页复习

1. 现实问题:为什么输入的 2 有时会变成 23

想做一个控制台购物小程序:用户输入商品名、单价和数量,程序计算小计。表面上只有一条乘法,真正写时却会碰到三个问题:键盘输入最初是什么类型,数字该放进哪种变量,+ 到底是在相加还是在拼文字。

例如,文字 "2" + "3" 的结果是 "23",整数 2 + 3 的结果才是 5。程序不会猜你的意思,它只按照类型和运算符规则执行。类型决定一份数据能做什么,变量只是给这份数据起名字。

这一课先把基础规则学扎实,不提前要求你掌握异常、BigDecimal、记录模式或复杂分层。金额在真实项目里会用 BigDecimal,但那是第 8 课的内容;本课先用 double 练习输入和运算,并明确它不适合最终的财务计算。

2. 最小可运行示例:先让输入真正参与计算

把下面内容保存为 ConsoleOrder.java,编译后运行:

import java.util.Scanner;

public class ConsoleOrder {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("商品名:");
        String name = scanner.nextLine();

        System.out.print("单价:");
        double unitPrice = scanner.nextDouble();

        System.out.print("数量:");
        int quantity = scanner.nextInt();

        double total = unitPrice * quantity;
        System.out.println(name + " × " + quantity + " = " + total);
    }
}
商品名:Java 入门书
单价:39.9
数量:2
Java 入门书 × 2 = 79.8

先不要急着加校验。第一次运行只观察四件事:name 保存文字,unitPrice 保存小数,quantity 保存整数,乘法产生新的 total。如果这四个变量的类型还说不清,后面的判断和业务对象都会变成死记硬背。

3. 语法拆解:变量、八种基本类型和表达式

变量声明的完整结构是:

数据类型 变量名 = 初始值;

int quantity = 2;
double unitPrice = 39.9;
boolean paid = false;
char level = 'A';

等号右边先计算,再把结果交给左边变量。= 是赋值,不是数学里的“相等”;比较相等要写 ==

Java 有八种基本类型:

类型常见用途示例这一课怎么记
byte很小范围整数、原始字节byte level = 10;先认识,不作为普通计数默认选择
short较小范围整数short year = 2026;先认识,业务代码较少直接使用
int普通整数和计数int quantity = 2;整数默认优先想到它
long更大范围整数、编号、毫秒值long id = 9_000_000_000L;大整数末尾常加 L
float单精度小数float rate = 0.5F;末尾加 F,业务代码较少默认使用
double普通小数计算double price = 39.9;本课用它练习,不用于最终财务金额
char单个字符char grade = 'A';单引号,只能放一个字符
boolean真或假boolean valid = true;只能是 truefalse

String 不是第九种基本类型,它是引用类型,用双引号表示文字。此时只需要会声明和拼接:

String name = "Java 入门书";
System.out.println("商品:" + name);

算术、比较和逻辑运算

int a = 7;
int b = 3;

System.out.println(a + b); // 10
System.out.println(a - b); // 4
System.out.println(a * b); // 21
System.out.println(a / b); // 2,两个 int 相除仍是 int
System.out.println(a % b); // 1,余数

System.out.println(a > b);          // true
System.out.println(a == b);         // false
System.out.println(a > 0 && b > 0); // true

整数除法会丢掉小数部分。想得到 2.333...,至少让一边成为小数:

double result = (double) a / b;

这里的 (double) 是显式类型转换。它先把 a 当作 double,然后进行小数除法。反方向把 double 转成 int 可能丢失小数,所以 Java 要求你明确写出转换并承担结果。

+ 为什么一会儿相加、一会儿拼接

System.out.println(10 + 20 + "元"); // 30元
System.out.println("合计" + 10 + 20); // 合计1020

表达式从左到右计算。第一行先得到整数 30,遇到字符串后再拼接;第二行一开始就是字符串,后面的数字都转成文字继续拼。看不清时加括号,不要靠背输出答案。

4. Scanner 调用链:键盘字符怎样进入变量

Scanner scanner = new Scanner(System.in); 可以拆成三步:

  1. System.in 代表标准输入,提供从键盘进入的字节。
  2. new Scanner(System.in) 创建一个 Scanner 对象,负责按规则切分和解析输入。
  3. scanner 保存这个对象的引用,后面通过它调用 nextInt()nextDouble()nextLine()

一次 int quantity = scanner.nextInt(); 的完整变化是:

键盘按下 2 和回车
  → Scanner 缓冲区收到字符 "2\n"
  → nextInt() 读取数字 token 并解析
  → 得到 int 值 2
  → 赋值给 quantity

各读取方法不是同一个意思:

方法读取到哪里常见用途
nextInt()读取下一个整数 token数量、年龄、菜单编号
nextDouble()读取下一个小数 token本课的小数练习
next()读取到空格前不含空格的单词
nextLine()读取到本行结束商品名、完整句子

最常见的坑是先 nextInt(),再 nextLine():整数读走了,回车还留在缓冲区,下一次 nextLine() 可能只读走这个回车,于是得到空字符串。

int quantity = scanner.nextInt();
scanner.nextLine(); // 只消费上一行剩下的回车
String remark = scanner.nextLine();

这不是 Scanner “抽风”,而是两个方法的结束规则不同。排查输入问题时,先写出缓冲区还剩哪些字符,比反复换方法更可靠。

5. 为什么这样设计:类型是编译器替你守住的边界

如果把数量写成 String quantity = "2",它可以显示,却不能直接参与可靠的数量比较;如果把是否付款写成 String paid = "yes",程序还要猜 yesYES1 是否代表同一件事。换成 intboolean 后,错误输入会在转换边界暴露,后面的代码只处理明确值。

基本类型变量直接保存简单值,StringScanner 等引用变量保存对象的引用。现阶段不需要背 JVM 内存图,只要能回答:变量里是整数值、真假值,还是指向一个对象的引用。

自动类型提升也来自安全边界:小范围整数参与计算时常先提升为 int;把大范围或小数结果塞回小类型,编译器会要求显式转换。编译器阻止的不是“写法不漂亮”,而是可能静默丢数据的操作。

6. 项目落点:今天的控制台输入以后会变成 HTTP 参数

控制台里的 Scanner 以后会被 Spring MVC 的参数绑定替代,但数据路线没有变:

键盘文字 → Scanner → int/double/String
HTTP 文字或 JSON → Spring 参数绑定 → Integer/BigDecimal/String

边界层负责把外部文字变成 Java 类型,业务层再计算和判断。不要把 Scanner 传进 Service,也不要让 Repository 接收一堆尚未解析的原始文字。这样输入方式从控制台换成网页时,业务计算仍能复用。

真实金额将在第 8 课换成 BigDecimal,因为 double 使用二进制近似表达小数,0.1 + 0.2 可能不是精确的 0.3。现在知道这个边界即可,不需要提前背 setScale 和舍入模式。

7. 易错排查与动手练习

遇到问题按“输入 → 类型 → 运算 → 输出”的顺序查:

  • 输入姓名只有第一个词:用了 next(),需要整行时改用 nextLine()
  • nextLine() 立刻得到空字符串:前面的 nextInt() 留下了回车,先消费一次剩余行。
  • 7 / 3 得到 2:两边都是整数;需要小数时把一边转换成 double
  • 输出变成 合计1020:字符串过早参与 +,用括号先完成数值加法。
  • 大整数编译失败:超出 int 范围时使用 long,整数字面量末尾加 L
  • 小数转整数编译失败:这是可能丢精度的窄化转换,必须明确写 (int) 并说明为什么允许丢失。

请独立完成一个“旅行费用计算器”:读取目的地、每天住宿费、天数和交通费,输出总费用。要求至少使用 Stringdoubleint、乘法和加法。然后再加三组实验:

  1. 7 / 3(double) 7 / 3 同时输出,解释差异。
  2. 输出 "总计:" + 10 + 20"总计:" + (10 + 20),解释计算顺序。
  3. 先读取天数,再读取带空格备注,复现并修复换行问题。

练习完成的标准不是“最后数字对了”,而是你能指着每个变量说出它的类型、值从哪里来、参与了哪个表达式、结果交给了谁。

8. 一页复习

  • 声明变量:类型 变量名 = 初始值;
  • 八种基本类型中,普通整数先想到 int,大整数用 long,真假用 boolean,单字符用 char
  • String 是引用类型;双引号表示字符串,单引号表示单个字符。
  • = 是赋值,== 是比较;比较和逻辑表达式的结果是 boolean
  • 两个 int 相除仍是整数;需要小数结果时让至少一边成为 double
  • + 只要遇到字符串就进入拼接;复杂表达式用括号明确顺序。
  • Scanner 是对象;nextIntnextDoublenextnextLine 的结束规则不同。
  • 学完这一课,你应当能从键盘输入一路追到变量、表达式和最终输出,而不是只记住一个完整示例。

本课按「JavaBaseDay02 的运算符与 Scanner 范围;正文和示例为原创重写」的学习范围组织,正文与示例均为本站原创整理。