From b76abae679238308d36863e003f851901cfdd763 Mon Sep 17 00:00:00 2001 From: e2hang <2099307493@qq.com> Date: Mon, 29 Dec 2025 23:41:10 +0800 Subject: [PATCH] New Java --- Class/readme.md | 263 ++++++++++++++++++++++++++++++++++++++++++++++++ readme.md | 112 +++++++++++++++++++++ 2 files changed, 375 insertions(+) create mode 100644 Class/readme.md create mode 100644 readme.md diff --git a/Class/readme.md b/Class/readme.md new file mode 100644 index 0000000..44b165d --- /dev/null +++ b/Class/readme.md @@ -0,0 +1,263 @@ +这两个问题问得非常精准,直接触及了 Java **工程化**的核心。 + +### 问题 1:什么时候用 public、static,什么时候单开文件? + +这是 Java 初学者最容易混淆的地方,我们可以这样理解: + +#### **1. 什么时候用 `public`?(决定“谁能访问”)** + +* **单开文件时**:如果你希望这个类能被整个项目中的其他类使用,就用 `public`。 +* **方法/属性**:如果你希望其他类能调用这个方法(比如 `getInfo()`),就用 `public`。 +* **如果不写**:默认是“包私有”,只有同一个文件夹下的类能访问。 + +#### **2. 什么时候用 `static`?(决定“是否属于类本身”)** + +* **核心逻辑**:`static` 意味着这个东西**不需要 `new` 就能用**。 +* **工具类/方法**:比如 `Math.sqrt()`,你不需要 `new Math()` 就能算平方根,这就是静态的。 +* **内部类**:如果你在一个类里面写另一个类,且不需要外部类的实例就能创建它,就用 `static`。 +* **注意**:在 `main` 方法里调用的本类方法,必须是 `static` 的。 + +#### **3. 什么时候单开一个文件?(决定“代码整洁度”)** + +* **Java 惯例**:**绝大多数情况下,一个文件只写一个类**,且文件名就是类名。 +* **你的 User 类**:虽然写在 `Main.java` 里能运行,但在做服务器开发时,`User` 是一个“模型(Model)”,应该单开一个 `User.java`。 +* **唯一例外**:如果一个类非常小,且只在某个类内部使用,可以写成“内部类”。 + +--- + +### 问题 2:如何引入其他路径的文件? + +在 Java 中,我们不用“文件路径”来找代码,而是用 **`package`(包)**。这就像是用“行政区划”代替“坐标”。 + +#### **第一步:给文件定包名(文件开头)** + +假设你有一个项目,结构如下: + +```text +src/ + ├── com.myapp.model/ + │ └── User.java + └── com.myapp.main/ + └── Main.java + +``` + +在 `User.java` 的第一行要写: + +```java +package com.myapp.model; + +public class User { ... } + +``` + +#### **第二步:引入(Import)** + +在 `Main.java` 中,如果你想用那个 `User` 类,你需要在文件开头使用 `import` 关键字: + +```java +package com.myapp.main; + +// 引入具体路径下的类 +import com.myapp.model.User; + +public class Main { + public static void main(String[] args) { + User u = new User(...); // 现在可以用了! + } +} + +``` + +#### **特殊的引入:`java.util.***` + +你之前用的 `import java.util.Scanner;` 其实就是引入了 Java 官方提供的“工具包”里的 `Scanner` 类。 + +--- + +### 💡 总结一下: + +1. **想给别人用**:加 `public`。 +2. **不想 `new` 就能用**:加 `static`。 +3. **正式写项目**:一个文件一个类,放在不同的 `package` 里。 + +**你现在可以尝试一下:新建两个文件 `User.java` 和 `Main.java`,把之前的代码拆开,看看能不能编译成功?这是迈向“真软件开发”的第一步!** + + +在 C++ 中我们叫 STL(Standard Template Library),在 Java 中,对应的这套东西叫做 **Java Collections Framework (Java 集合框架)**。 + +它们全部位于 **`java.util`** 这个包下面。所以使用前,你得先 `import java.util.*;`。 + +--- + +### 1. Java 集合框架大蓝图 + +Java 的集合主要分为两大派系: + +* **Collection 接口**:存的是单个元素(类似 C++ 的 `vector`, `set`, `list`)。 +* **Map 接口**:存的是键值对(Key-Value,类似 C++ 的 `map`)。 + +--- + +### 2. 常用集合对比与用法 + +#### **A. 动态数组:`ArrayList**` + +最常用的,对应 C++ 的 `std::vector`。 + +* **特点**:查找快,增删慢(尾部除外)。 +* **用法**: +```java +ArrayList list = new ArrayList<>(); +list.add("Java"); +list.get(0); // 访问 + +``` + + + +#### **B. 集合:`HashSet` 与 `TreeSet**` + +对应 C++ 的 `std::unordered_set` 和 `std::set`。 + +* **`HashSet`**:无序,速度极快(基于哈希表)。 +* **`TreeSet`**:自动排序(基于红黑树)。 +* **用法**: +```java +Set set = new HashSet<>(); +set.add(1); +set.add(1); // 重复元素会被忽略 +System.out.println(set.contains(1)); // true + +``` + + + +#### **C. 映射:`HashMap` 与 `TreeMap**` + +对应 C++ 的 `std::unordered_map` 和 `std::map`。这是**服务器开发**中最常用的数据结构,用于存储配置、用户信息等。 + +* **`HashMap`**:键值对,Key 不能重复。 +* **用法**: +```java +HashMap userAssets = new HashMap<>(); +userAssets.put("Wan", -114514.0); // 存入 +double asset = userAssets.get("Wan"); // 取出 + +``` + + + +--- + +### 3. 一个实战小例子 + +既然你之前写了 `User` 类,我们看看如何用 `Map` 把用户 ID 和对象关联起来,这样查询时就不需要循环遍历整个数组了: + +```java +import java.util.HashMap; +import java.util.Map; + +public class TestCollections { + public static void main(String[] args) { + // 创建一个 Map,Key 是 ID (String),Value 是 User 对象 + Map userMap = new HashMap<>(); + + // 存入数据 + userMap.put("0", new User("Wan", "0", 0, -114514)); + userMap.put("1", new User("Zhang", "1", 1, 114514)); + + // 模拟服务器查询:通过 ID 直接秒杀查询,不需要 for 循环 + String searchId = "0"; + if (userMap.containsKey(searchId)) { + userMap.get(searchId).getInfo(); + } else { + System.out.println("用户不存在"); + } + } +} + +``` + +--- + +### 4. 关键区别(Java vs C++) + +* **泛型**:Java 使用 ``,注意必须是对象类型(包装类),不能直接用 `int`,得写 `Integer`;不能直接用 `double`,得写 `Double`。 +* **迭代器**:虽然 Java 也有 `Iterator`,但现在更流行用 `forEach` 或者是 `Stream API`。 +* **内存管理**:你不需要像 C++ 那样担心 `delete` 集合里的对象,Java 的 GC(垃圾回收)会自动处理。 + +--- + +### 🛠️ 建议挑战 + +你可以尝试把之前代码里的 `User[] user = {...}` 换成 `ArrayList`,然后试试看: + +1. 用 `list.add()` 添加几个用户。 +2. 用 `list.remove(0)` 删除第一个用户。 +3. 看看 `list.size()` 的变化。 + +**你想深入了解一下为什么 Java 集合里不能存 `int` 这种基本类型(装箱/拆箱机制),还是直接动手试试 Map 的操作?** + +``` cpp +class Solution { +    void flip(TreeNode* &left, TreeNode* &right){ +        if(left == null && right == null) return; +        TreeNode tmp = left; +        left = right; +        right = tmp; + +        flip(left->left, left->right); +        flip(right->left, right->right); +    } +    TreeNode* flipTree(TreeNode* root) { +        if(root == null) return root; +        flip(root->left, root->right); +        return root; +    } +} +``` + +完全正确!你这一句话就点到了 Java 内存管理的死穴。 + +作为一个 C++ 选手,你可以把 Java 的声明和初始化拆解为这两步: + +1. **声明 `TreeNode node;**`:这相当于 C++ 里的 `TreeNode* node = nullptr;`。在栈上只给了你一个 8 字节(64位系统)的空间,里面存的是全零,啥也干不了,一用就报 `NullPointerException`。 +2. **执行 `new TreeNode()**`:这相当于 C++ 里的 `new` 关键字。JVM 跑到堆(Heap)里划拉出一块内存,把对象的成员变量(val, left, right)填进去,然后把这块地盘的**首地址**返回给栈上的 `node`。 + +--- + +### 💡 一个让你“豁然开朗”的对比 + +在 C++ 里,你有两种选法;而在 Java 里,你只有一种选法。 + +| 特性 | C++ (两种都有) | Java (只有一种) | +| --- | --- | --- | +| **栈对象** | `TreeNode node;` (直接分配内存) | **不存在** (只有基本类型能进栈) | +| **堆对象** | `TreeNode* node = new TreeNode();` | `TreeNode node = new TreeNode();` | +| **指针算术** | `node++` (可以) | **禁止** (安全第一) | +| **内存释放** | `delete node;` (手动) | **自动** (GC 负责) | + +--- + +### 🚀 既然“指针本质”你已经通了,那我们聊聊“服务器” + +在 Java 服务器开发中(比如使用 **Spring Boot** 框架),这种“new 了才分配地址”的特性衍生出了一个极度重要的概念:**依赖注入 (Dependency Injection, DI)**。 + +**场景:** 你的 `LoginService` 需要一个 `DatabaseConnector`。 + +* 在 C++ 里,你可能要在构造函数里手写 `new`。 +* 在 Java 里,你只需要声明 `private DatabaseConnector db;`,然后打个注解。 +* **本质:** 框架在后台偷偷帮你执行了 `new`,并把那个**地址(引用)**塞给了你的变量。 + +这就是为什么 Java 适合做大型软件:它通过管理这些“指针”的指向,让你不需要关注对象是怎么创建的,只需要关注怎么用它。 + +--- + +### 🧠 最后一个关于指针的“脑筋急转弯” + +既然你说类创建出来默认是指针(引用),那 **`String s1 = "Hello";`** 为什么不需要 `new`? + +这是 Java 为了性能搞的一个“特权”。如果你感兴趣,我们可以聊聊 **字符串常量池 (String Pool)** —— 这也是 Java 节省内存的一大杀手锏。 + +**或者,你现在想直接上手写个带“指针逻辑”的小 Demo(比如链表反转)来验证一下你的理解?** \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..722876d --- /dev/null +++ b/readme.md @@ -0,0 +1,112 @@ +这份笔记为你梳理了 Java 开发中最核心的语法和类型体系。你可以把它当作一张“速查表”,重点标注了和 C/C++ 的差异点。 + +--- + +## 1. Java 数据类型大地图 + +Java 的类型系统分为两大类:**基本类型**和**引用类型**。 + +### ① 基本类型 (Primitive Types) + +Java 的基本类型长度是**固定**的,不随操作系统位数改变(这是跨平台的保证)。 + +| 类型 | 大小 | 默认值 | 包装类 (用于集合) | 备注 | +| --- | --- | --- | --- | --- | +| **byte** | 1 byte | 0 | Byte | 很少用,多用于二进制流 | +| **short** | 2 bytes | 0 | Short | - | +| **int** | 4 bytes | 0 | **Integer** | 最常用 | +| **long** | 8 bytes | 0L | Long | 赋值需加 `L` 后缀 | +| **float** | 4 bytes | 0.0f | Float | 赋值需加 `f` 后缀 | +| **double** | 8 bytes | 0.0 | Double | 常用浮点数 | +| **char** | 2 bytes | '\u0000' | Character | **UTF-16 编码**,存一个汉字没问题 | +| **boolean** | 1 bit | false | Boolean | 只有 `true/false`,不能用 0/1 | + +### ② 引用类型 (Reference Types) + +除了上面 8 种,剩下的全是引用类型(类似于 C 的指针,但你不能直接操作内存地址)。 + +* **类 (Class)**:如 `String`, `User` +* **接口 (Interface)**:如 `List` +* **数组 (Array)**:如 `int[]`, `User[]` + +--- + +## 2. 核心语法速记 + +### ① 变量与常量 + +```java +int age = 18; // 变量 +final double PI = 3.1415; // 常量 (类似 C++ 的 const) + +``` + +### ② 运算符 (与 C 几乎一致) + +* 算术:`+`, `-`, `*`, `/`, `%`, `++`, `--` +* 关系:`==`, `!=`, `>`, `<`, `>=`, `<=` +* 逻辑:`&&` (短路与), `||` (短路或), `!` +* **特殊**:`+` 可以用于字符串拼接,如 `"Age: " + age`。 + +### ③ 条件与循环 + +```java +// 条件 +if (score > 60) { ... } else { ... } + +// 循环 (和 C 没区别) +for (int i = 0; i < 10; i++) { ... } +while (condition) { ... } + +// 增强型 for (专门遍历集合和数组) +for (String name : nameList) { + System.out.println(name); +} + +``` + +--- + +## 3. 面向对象三要素 (封装、继承、多态) + +* **封装**:使用 `private` 隐藏属性,通过 `public` 的 `getter/setter` 方法暴露。 +* **继承**:使用 `extends` 关键字。Java 是**单继承**,一个儿子只能有一个亲爹。 +* **多态**:父类引用指向子类对象 `List list = new ArrayList();`(这是后端开发的灵魂)。 + +--- + +## 4. Java 集合框架 (STL 对应版) + +在 `java.util` 包下,这是做服务器开发最常用的工具: + +| 功能 | Java 接口 | 常用实现类 | C++ 对应 | +| --- | --- | --- | --- | +| **动态数组** | `List` | `ArrayList` | `std::vector` | +| **链表** | `List` | `LinkedList` | `std::list` | +| **哈希表** | `Map` | **`HashMap`** | `std::unordered_map` | +| **排序映射** | `Map` | `TreeMap` | `std::map` | +| **唯一集合** | `Set` | `HashSet` | `std::unordered_set` | + +--- + +## 5. 两个“必须知道”的避坑指南 + +### 🔴 避坑 1:字符串比较 + +* **错误**:`if (str == "hello")` (这是在比较内存地址) +* **正确**:`if (str.equals("hello"))` (这是在比较内容) + +### 🔴 避坑 2:自动装箱与拆箱 + +Java 集合不能直接存基本类型(如 `int`),必须存包装类(`Integer`)。 + +```java +ArrayList list = new ArrayList<>(); +list.add(10); // 自动装箱:把 int 变成 Integer 对象 +int val = list.get(0); // 自动拆箱:把 Integer 变成 int + +``` + +--- + +**这份笔记你可以先存着。如果你想练习,我可以给你一个涉及到“继承和多态”的小案例,这对于理解 Spring 等后端框架非常有帮助。要试试吗?** \ No newline at end of file