Java 快速入门笔记:从基础语法到 Spring Boot 实战
本文面向有其他语言(如 Go、C++)编程经验的开发者,系统梳理了 Java 语言的核心知识点,包括 JDK/JRE 区别、Maven 项目管理、数据类型、集合框架、IO 模式、多线程编程、Spring Boot 快速入门和 JNI 调用等内容,帮助你快速建立 Java 知识体系。
一、Java 开发环境
1.1 JDK 与 JRE 的区别
JDK(Java Development Kit) 是 Java 开发工具包,包含了编译器(javac)、调试器、Java 运行时等工具。JRE(Java Runtime Environment) 是 Java 运行时环境,只包含运行 Java 程序所需的组件。
简单来说:JDK 包含 JRE。如果你只需要运行 Java 程序,安装 JRE 即可;如果要开发 Java 程序,需要安装 JDK。
JDK 目录结构(JDK 8):
Java/
├── jdk1.8.0_351/ # JDK 安装目录
│ ├── bin/ # 开发工具(javac、java、jar 等)
│ ├── lib/ # 开发库
│ └── jre/ # 自带的 JRE
└── jre1.8.0_351/ # 独立的 JRE
API 文档参考:
- Java 8 标准库 API:https://www.matools.com/api/java8
- Java 学习网站(含 Spring 教程):https://www.w3cschool.cn/java/dict.html
1.2 Maven 项目管理
Maven 是 Java 的项目管理和构建工具(类似于 C++ 的 CMake、Go 的 Go Modules),负责依赖管理、编译、打包等。
安装与配置国内镜像源:
在 Maven 安装目录的 conf/settings.xml 中替换镜像配置:
xml
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
常用 Maven 命令:
bash
# 清理 + 编译 + 打包(跳过测试)
mvn clean compile package -Dmaven.test.skip=true
# 清理已编译的目标文件
mvn clean
# 打包
mvn package
# 安装依赖到本地仓库
mvn install
pom.xml 是 Maven 项目的核心配置文件(类似于 CMake 的 CMakeLists.txt),定义了项目依赖、插件和构建配置。
Java 工程以 jar 包的形式运行,Maven 负责将源码编译并打包为可执行的 jar 文件。
1.3 IDE 选择
推荐使用 IntelliJ IDEA(官网有免安装的社区版),开箱即用。配置要点:
- 设置 Maven 路径和
settings.xml地址 - 设置 JDK 路径
VSCode 开发 Java: 安装 Java Extension Pack 后,可以通过以下方式引入第三方 jar 包:
json
// settings.json
{
"java.project.referencedLibraries": [
"lib/**/*.jar",
"c:\\Users\\Mr.Zhou\\Downloads\\javax.mail-1.6.2.jar"
]
}
1.4 Java 文件与类的基本规则
- 一个 Java 文件中只能存在一个
public类 - Java 文件命名必须是
public 类名.java - 类名建议大写开头,方法与成员变量建议小写开头
二、基础数据类型与访问修饰符
2.1 基本数据类型
Java 中没有有符号与无符号之分,全是有符号类型:
| 类型 | 存储大小 | 取值范围 | 备注 |
|---|---|---|---|
boolean |
1 字节 | true / false |
布尔型 |
byte |
1 字节 | -128 ~ 127 | 字节(存储 ASCII 或二进制) |
char |
2 字节 | 0 ~ 65535 | 字符(如 char c = '你') |
short |
2 字节 | -32768 ~ 32767 | 短整型 |
int |
4 字节 | -2^31 ~ 2^31-1 | 整型 |
long |
8 字节 | -2^63 ~ 2^63-1 | 长整型(常量加 L 后缀) |
float |
4 字节 | --- | 单精度浮点(常量加 F 后缀) |
double |
8 字节 | --- | 双精度浮点(默认) |
包装类型(Wrapper Class): 每个基本类型都有对应的包装类(Integer、Long、Double 等),在集合框架中只能使用包装类型。
java
// 字符串转数字
int d = Integer.valueOf("1234");
// 数字转字符串
String s = String.valueOf(1234);
// 或
String s = Integer.toString(1234);
2.2 四种访问修饰符
| 修饰符 | 同一个类 | 同一个包 | 子类 | 任何地方 |
|---|---|---|---|---|
public |
Y | Y | Y | Y |
protected |
Y | Y | Y | |
default(不写) |
Y | Y | ||
private |
Y |
注意:
protected和private不能修饰外部类- 不写修饰符则默认为
default,default关键字不需要写出来(写出来反而会报错) synchronized修饰符可以与四种访问修饰符组合使用,表示方法同一时间只能被一个线程访问
2.3 引用类型 vs 值类型
与 Go 语言有明显区别:Java 中除了 8 种基础数据类型(boolean、byte、char、short、int、long、double、float)以外,所有类类型都是引用类型。基础数据类型的数组类型也是引用类型。
java
// Go 中数组传递是值拷贝
// Java 中数组传递是引用传递
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1;
arr1[0] = 99;
System.out.println(arr2[0]); // 99(跟着变了)
三、String 与字符串操作
3.1 String 的不可变性
Java 的 String 与 Go 的 string 一样,定义后便无法修改。如需可修改的字符串,使用 StringBuffer(线程安全)或 StringBuilder(非线程安全,性能更好):
java
// String 不可变
String s = "hello";
s = s + " world"; // 实际是创建了新的 String 对象
// StringBuilder 可变
StringBuilder sb = new StringBuilder("hello");
sb.append(" world");
String result = sb.toString();
3.2 字符串池
Java 中通过双引号创建的字符串会进入字符串常量池,相同内容的字符串共享同一引用:
java
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2); // true(指向字符串池中同一对象)
System.out.println(s1 == s3); // false(s3 在堆上创建新对象)
System.out.println(s1.equals(s3)); // true(值相等)
推荐使用 .equals() 比较字符串内容 ,而不是 ==。
3.3 常用字符串操作
java
// 格式化字符串(类似 C 的 sprintf)
String formatted = String.format("Name: %s, Age: %d", "Tom", 25);
// 大小写转换(Go 中需要 strings 包,Java String 自带)
String upper = "hello".toUpperCase();
String lower = "WORLD".toLowerCase();
// 字符串与字节数组互转
byte[] bytes = "hello".getBytes();
String fromBytes = new String(bytes);
// String.valueOf() 万能转换
String s1 = String.valueOf(123); // 数字转字符串
String s2 = String.valueOf(true); // 布尔转字符串
String s3 = String.valueOf(3.14); // 浮点转字符串
注意: 所有类型的 toString() 方法并不是都返回有意义的字符串内容。大部分对象直接调用 toString() 输出的是地址信息,转之前需要确认该类是否重写了 toString()。
四、时间操作
java
import java.text.SimpleDateFormat;
import java.util.Date;
// 获取时间戳(两种方式)
long ts1 = System.currentTimeMillis();
long ts2 = new Date().getTime();
// Date 格式化
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String formatted = sdf.format(new Date());
// printf 格式化时间(方便)
System.out.printf("%tF %tT", new Date(), new Date());
// 等价于 yyyy-MM-dd HH:mm:ss
五、集合框架
Java 集合框架是处理数据集合的核心工具,对应 Go 中的 slice 和 map,但功能更加丰富。
5.1 List(列表)
List 是有序可重复的集合,对应 Go 的 slice:
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
// 创建 ArrayList
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("cherry");
// 访问元素
String first = list.get(0); // apple
// 遍历
for (String item : list) {
System.out.println(item);
}
// 数组转 List
String[] arr = {"a", "b", "c"};
List<String> listFromArray = Arrays.asList(arr);
// 数组截取(类似 Go 的 slice[start:end])
String[] original = {"a", "b", "c", "d", "e"};
String[] sub = Arrays.copyOfRange(original, 1, 4); // {"b", "c", "d"}
注意: ArrayList 的泛型参数只支持包装类型,不支持基本类型(如 int 要用 Integer)。
5.2 Map(映射)
Map 是键值对集合,对应 Go 的 map:
java
import java.util.HashMap;
import java.util.Map;
// 创建 HashMap
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 95);
scores.put("Bob", 87);
scores.put("Charlie", 92);
// 访问
int score = scores.get("Alice"); // 95
// 判断 key 是否存在
if (scores.containsKey("Alice")) {
System.out.println("Found Alice");
}
// 遍历
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
5.3 Set(集合)
Set 是无序不重复的集合:
java
import java.util.HashSet;
import java.util.Set;
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("apple"); // 重复元素不会添加
System.out.println(set.size()); // 2
5.4 迭代器
java
import java.util.Iterator;
import java.util.List;
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
// 使用迭代器遍历(可以在遍历时安全删除元素)
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
if (item.equals("b")) {
it.remove(); // 安全删除
}
}
六、接口与抽象类
6.1 抽象类
java
abstract class Animal {
// 抽象方法(只有声明,没有实现)
abstract void makeSound();
// 普通方法
void sleep() {
System.out.println("sleeping...");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Woof!");
}
}
抽象类总结:
- 抽象类不能被实例化
- 抽象类中不一定包含抽象方法,但有抽象方法的类必定是抽象类
- 构造方法和
static方法不能声明为抽象方法 - 子类必须实现所有抽象方法,否则子类也必须声明为抽象类
6.2 接口(Interface)
Java 的接口和 Go 的接口概念非常相似,只不过 Go 是鸭子模式(隐式实现),Java 需要使用 implements 关键字(显式实现):
java
interface Writer {
int write(byte[] b);
}
// 实现接口
class FileWriter implements Writer {
@Override
public int write(byte[] b) {
// 实现写入逻辑
return b.length;
}
}
// 使用接口作为参数
private static int testInterface(Writer w, byte[] data) {
return w.write(data);
}
接口特点:
- 接口不能用于实例化对象
- 接口没有构造方法
- 接口中所有方法默认是抽象的(Java 8 后可用
default修饰非抽象方法) - 接口不能包含成员变量(除
static和final变量) - 接口支持多继承
七、IO 模式(BIO / NIO / AIO)
7.1 三种 IO 模式对比
| 模式 | 全称 | 特点 |
|---|---|---|
| BIO | Block IO(阻塞 IO) | 最简单,一个连接需要一个线程处理 |
| NIO | Not-Block IO(非阻塞 IO) | 类似 Linux 的 select/epoll 多路复用,一个线程处理大量连接 |
| AIO | Asynchronous IO(异步 IO) | 异步非阻塞,操作系统完成后再回调通知 |
7.2 ByteBuffer(NIO 核心)
java.nio.ByteBuffer 是 NIO 中的核心缓冲区类,类似于 Go 的 bytes.Buffer:
java
import java.nio.ByteBuffer;
import java.util.Arrays;
// 分配内存
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 写入数据
buffer.put("hello world".getBytes());
// 读取数据
byte[] allData = buffer.array();
// 获取实际写入的数据长度
int length = buffer.position();
// 获取有效数据
byte[] validData = Arrays.copyOfRange(allData, 0, length);
注意: ByteBuffer 需要预先指定容量,追加数据超出容量会抛异常。如果需要自动管理容量,可以使用 StringBuilder 代替。
八、多线程编程
Java 内置多线程支持,创建线程比很多语言更简单。
8.1 三种创建线程的方式
方式一:实现 Runnable 接口
java
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Thread running: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
Thread th = new Thread(new MyRunnable(), "my-thread");
th.start(); // start() 内部调用 run()
}
}
方式二:继承 Thread 类
java
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running: " + getName());
}
}
public class Main {
public static void main(String[] args) {
MyThread th = new MyThread();
th.start();
}
}
方式三:实现 Callable 接口(有返回值)
java
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}
public class Main {
public static void main(String[] args) throws Exception {
FutureTask<Integer> task = new FutureTask<>(new MyCallable());
Thread th = new Thread(task);
th.start();
// 获取返回值(类似 C++ 的 future/promise)
Integer result = task.get();
System.out.println("Sum: " + result); // 5050
}
}
本质上,以上三种方式都是围绕 Thread 类的 run 方法。 start() 方法会启动新线程并调用 run(),直接调用 run() 只是在当前线程执行。
8.2 synchronized 同步
java
class Counter {
private int count = 0;
// 同步方法:同一时间只能被一个线程访问
public synchronized void increment() {
count++;
}
// 同步代码块
public void decrement() {
synchronized (this) {
count--;
}
}
public int getCount() {
return count;
}
}
九、Spring Boot 快速入门
Spring Boot 是 Java 生态中最流行的 Web 开发框架,极大简化了 Spring 应用的配置和部署。
9.1 引入第三方库
Java 引入第三方库的方式:
- Maven/Gradle 依赖管理: 在
pom.xml中添加依赖(推荐) - 手动引入 jar 包: 将 jar 放入
classpath或%JAVA_HOME%\jre\lib\ext目录 - VSCode 引用: 在
settings.json的java.project.referencedLibraries中配置
xml
<!-- pom.xml 中添加 Spring Boot 依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
9.2 项目分层结构
Java Web 项目通常采用 MVC 分层架构:
src/main/java/com/example/
├── controller/ # 控制层:处理 HTTP 请求
├── service/ # 业务层:处理业务逻辑
├── dao/ # 数据访问层:数据库操作
├── model/
│ ├── entity/ # 实体类:与数据库表对应
│ ├── vo/ # 视图对象:与前端页面对应
│ └── dto/ # 数据传输对象:entity 与 vo 之间的转换
└── Application.java # 启动类
9.3 简单的 REST API 示例
java
// 启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 控制器
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/hello")
public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
return String.format("Hello, %s!", name);
}
@PostMapping("/user")
public User createUser(@RequestBody User user) {
// 处理逻辑
return userService.save(user);
}
}
9.4 MyBatis 条件查询
在 DAO 层的 XML 映射文件中,可以直接在 SQL 中使用条件判断:
xml
<select id="queryRecords" resultType="PatrolRecord">
SELECT id, patrol_line_plan_id, name, company_code
FROM patrol_line_record
WHERE delete_flag = 0
AND company_code REGEXP CONCAT('^(',
CONCAT_WS('|',
<foreach collection="orgCodes" item="code" separator=",">
#{code}
</foreach>
), ')')
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="startDate != null and endDate != null">
AND line_date BETWEEN #{startDate} AND #{endDate}
</if>
<if test="statusId != null">
AND status_id = #{statusId}
</if>
ORDER BY create_time DESC
</select>
这种方式的优点是将条件逻辑写在 SQL 中,避免在业务层做过多的 if 判断。
十、JNI(Java Native Interface)调用
JNI 允许 Java 代码调用本地(Native)方法,即 C/C++ 编写的动态链接库。
10.1 基本流程
- 在 Java 类中声明
native方法 - 使用
javac编译 Java 文件 - 使用
javah生成 C/C++ 头文件 - 用 C/C++ 实现本地方法
- 编译为动态链接库(
.dll或.so) - 在 Java 中加载库并调用
java
public class NativeDemo {
// 加载本地库
static {
System.loadLibrary("mynative");
}
// 声明本地方法
public native String sayHello(String name);
public static void main(String[] args) {
NativeDemo demo = new NativeDemo();
String result = demo.sayHello("World");
System.out.println(result);
}
}
十一、常用工具与框架
11.1 JavaDoc 文档生成
类似 Go 的 godoc,Java 提供了 javadoc 工具,可以按照标准文档注释自动生成 HTML 文档:
java
/**
* 计算两个整数的和
* @param a 第一个加数
* @param b 第二个加数
* @return 两数之和
*/
public int add(int a, int b) {
return a + b;
}
bash
# 生成文档
javadoc -d doc src/*.java
11.2 定时任务框架
xxl-job 是 Java 中常用的分布式任务调度框架,用于管理和执行定时任务,提供 Web UI 管理界面,支持任务执行记录查看。
11.3 Java 与 Go 常用操作对比
| 操作 | Java | Go |
|---|---|---|
| 字符串转数字 | Integer.valueOf("123") |
strconv.Atoi("123") |
| 数字转字符串 | String.valueOf(123) |
strconv.Itoa(123) |
| 字符串大小写 | s.toUpperCase() |
strings.ToUpper(s) |
| 字节数组互转 | "hello".getBytes() |
[]byte("hello") |
| 数组截取 | Arrays.copyOfRange(arr, s, e) |
arr[s:e] |
| 可变字符串 | StringBuilder |
bytes.Buffer |
| 动态数组 | ArrayList<T> |
slice |
| 哈希表 | HashMap<K,V> |
map[K]V |
| 格式化字符串 | String.format() |
fmt.Sprintf() |
总结
Java 作为一门成熟的企业级编程语言,拥有极其丰富的生态和完善的工具链。本文涵盖了以下核心知识点:
- 开发环境: JDK/JRE 区别、Maven 项目管理、IDE 配置
- 基础语法: 8 种基本数据类型、4 种访问修饰符、引用类型与值类型的区别
- 字符串操作: String 不可变性、字符串常量池、StringBuilder
- 集合框架: ArrayList(动态数组)、HashMap(哈希表)、Set(集合)、迭代器
- IO 模式: BIO(阻塞)、NIO(非阻塞多路复用)、AIO(异步非阻塞)
- 多线程编程: 三种创建线程方式、synchronized 同步机制
- Spring Boot: 快速构建 REST API、项目分层结构、MyBatis 条件查询
- JNI 调用: Java 调用 C/C++ 本地方法
- 常用工具: JavaDoc 文档生成、xxl-job 定时任务
Java 的强类型系统、成熟的集合框架和强大的生态使其成为企业级应用开发的首选语言。对于有 Go/C++ 背景的开发者,Java 的面向对象特性和丰富的标准库会带来不同的编程体验。
原始笔记来源:
zyh/LearnJava.java