Day 1 · Java 入门与基本数据类型
语言定位:为什么需要 Java
课堂开头先把几门语言放在一起比了一遍,重点是「什么场景该用什么」。
| 语言 | 类型与语法特征 | 多态方式 | 主要场景 |
|---|---|---|---|
| Python | 动态强类型;一个 .py 就是一个模块;注释用 # 或三引号;换行结束语句、缩进划分代码块 | 鸭子类型:既可以是强多态(父类引用指向子类对象),也可以是弱多态(一个方法有多种形态) | 中小型项目 |
| Java | 静态强类型,类型编译期确定;一个 .java 必须有同名的 public class;入口固定为 public static void main(String[] args);注释 //、/* */、/** */;; 结束语句,{} 划分代码块 | 接口 / 继承 + 虚方法 | 大型后端服务 |
| C / C++ | 性能极致,手动管理内存 | — | 游戏引擎、嵌入式、操作系统 |
| Go | — | — | 微服务、DevOps 工具链 |
| JavaScript | 浏览器原生、事件驱动 | — | 前端、Node 后端、小程序 |
补充整理:原稿把 Python 写成「动态强类型,编译期确定」,这两句是冲突的—— 动态类型恰恰是运行时才确定类型,「编译期确定类型」是 Java 这类静态语言的特征。 另两个词也别混:强类型说的是不允许隐式做不安全的类型转换(Python 和 Java 都是强类型), 静态 / 动态说的是类型检查发生在编译期还是运行时。所以准确说法是 「Python 动态强类型,Java 静态强类型」。
Python 的适用边界
Python 的高并发、集群、微服务这套生态并不完整,只能满足中小型项目、用户数少的情况;用户量上来之后就撑不住。
补充整理:这句话说的是运行时模型与生态的取舍,不是「Python 不能写大项目」。 瓶颈主要在 GIL 限制多线程 CPU 并行、动态类型带来的运行时开销,以及服务治理 / RPC / 可观测性这套生态不如 JVM 成熟。工程上常见做法是 Python 负责模型与胶水层, 高并发的服务层交给 Java / Go——这也是这个博客主线(Python + FastAPI)之外还要学 Java 的原因。
Python 的模块入口
if __name__ == "__main__":
main()作用:让模块被 import 时不执行主逻辑,只有直接运行该文件时才走主入口。
补充整理:原稿这一行写到
if __main__ ==就断了。完整写法是if __name__ == "__main__":,注意是__name__(双下划线 name),不是__main__; 末尾的冒号和下一行缩进也不能少。Java 里对应的是固定入口public static void main(String[] args),由 JVM 直接调用,不需要这种判断。
1.1 简介与环境搭建
- JVM(Java Virtual Machine):Java 虚拟机,负责运行
.class字节码文件 - JRE(Java Runtime Environment):Java 运行时环境 = JVM + Java 内置类库
- JDK(Java Development Kit):Java 开发工具包 = JRE + 编译工具(
javac、调试、打包),编译之后得到.class文件
补充整理:三者是逐层包含的关系
JDK ⊃ JRE ⊃ JVM。写代码、编译要装 JDK, 只运行打好的程序理论上 JRE 就够(JDK 9 之后不再单独分发 JRE,改用jlink裁剪运行时)。一次完整的执行链路:
bashjavac Hello.java # 编译 → Hello.class(字节码) java Hello # JVM 加载字节码 → 解释执行 + JIT 热点编译所谓「一次编译,到处运行」,跨平台的是字节码,不是 JVM 本身—— 各操作系统要装各自版本的 JVM,由它把同一份字节码翻译成本地机器指令。
1.3 数据类型
存储单位换算
| 单位 | 换算 |
|---|---|
| 1 TB | 1024 GB |
| 1 GB | 1024 MB |
| 1 MB | 1024 KB |
| 1 KB | 1024 字节 |
| 1 字节 | 8 bit(八位二进制) |
八种基本数据类型
| 分类 | 类型 | 占用 | 说明 |
|---|---|---|---|
| 整数 | byte | 1 字节 | 微整型 |
| 整数 | short | 2 字节 | 小整型 |
| 整数 | int | 4 字节 | 默认整数类型 |
| 整数 | long | 8 字节 | 长整型,要声明 long 字面量需加 L |
| 浮点 | float | 4 字节 | 单精度,字面量需加 f(如 0.0f) |
| 浮点 | double | 8 字节 | 双精度,默认小数类型(0.0) |
| 字符 | char | 2 字节 | 只有内容长度为 1 且放在单引号里的才是字符 |
| 布尔 | boolean | 1 字节 | 默认 false |
默认值:
- 整数类型都是
0 - 小数类型都是
0.0 - 布尔类型是
false - 引用数据类型是
null(Day 2 讲)
String 不是基本类型,是引用类型,用双引号。Python 里严格来说没有字符类型,引号里长度为 1 的也还是字符串。
补充整理:几个最容易踩坑的地方——
- 字面量的默认类型:
123是int,3.14是double。所以long n = 9999999999;和float f = 3.14;都会直接编译报错(大数超出 int 范围、 double 不能隐式收窄成 float),必须写成9999999999L/3.14f。char用单引号'A',String用双引号"A",写反直接编译失败;char本质是无符号 2 字节整数,可以参与运算('A' + 1得到66)。boolean的大小 JVM 规范没有精确规定:作为局部变量通常按int(4 字节)处理, 在boolean[]里通常按 1 字节处理,不能简单记成「1 字节」。它是唯一不能和int互相转换的基本类型——if (1) { }在 Java 里非法,必须写布尔表达式。- 默认值只对成员变量生效。局部变量没有默认值,必须先初始化才能使用(Day 2 详述)。
- 浮点数存在精度问题,涉及金额一律用
BigDecimal,不要用double做加减。
