快速学习Java

前言

Java 的核心优势:为什么企业偏爱它?
“一次编写,到处运行”的跨平台能力:这是 Java 最标志性的特点。Java 代码编译后生成的不是特定平台的机器码,而是中间态的字节码(.class 文件)。这个字节码运行在 Java 虚拟机 (JVM) 上,而 JVM 针对不同平台(Windows、Linux、macOS)有不同版本 。只要目标平台安装了 JVM,同一个字节码文件就能直接运行,彻底解决了 C/C++ 程序因操作系统或库依赖不同而需要重新编译的痛点 。

自动化的内存管理(垃圾回收 GC) :在 C/C++ 中,你需要手动 malloc/free 或 new/delete,稍有不慎就会内存泄漏。Java 则内置了垃圾回收器,它会自动监测并回收不再使用的对象内存 。这极大减少了内存泄漏和悬垂指针等令人头疼的问题,让你从繁琐的内存管理中解放出来,更专注于业务实现 。

庞大且成熟的生态系统:Java 拥有全球最大、最成熟的开发者社区之一。这意味着你几乎能找到解决任何问题的现成轮子 :

企业级框架:Spring 全家桶(Spring Boot, Spring Cloud, Spring MVC)是业界标准,极大简化了企业级应用和微服务的开发。

构建工具:Maven 和 Gradle 能帮你自动化地管理项目依赖、构建和打包,告别手动管理 .jar 包的混乱。

丰富的类库:从网络通信到数据处理,Java 标准库(Java SE API)本身已经非常强大,再加上 Apache Commons、Google Guava 等第三方库,几乎无所不能。

一、 C++ 与 Java 核心概念对比表

核心概念C++Java解读
程序入口int main(int argc, char* argv[]) { ... }public static void main(String[] args) { ... }Java 的 main 方法必须放在类中,public 表示全局可访问,static 表示属于类而非实例,void 表示无返回值。
编译运行编译: g++ foo.cc -o outfile
运行: ./outfile
编译: javac Foo.java(生成 Foo.class
运行: java Foo
C++ 编译为可执行文件直接运行;Java 编译为字节码,由 JVM 解释/编译执行。
输出语句cout << "Hello" << endl;System.out.println("Hello");Java 通过 System 类的 out 对象的 println 方法实现输出。
布尔类型boolboolean关键字不同,但用法一致。
常量const int x = 5;final int x = 5;Java 使用 final 声明不可变常量。
对象创建栈上: MyClass obj;
堆上: MyClass* obj = new MyClass();
MyClass obj = new MyClass();Java 对象始终在堆上分配,obj 为引用(类似指针,但无算术运算)。
成员访问栈对象: obj.field
指针: obj->field
obj.fieldJava 统一使用 . 访问成员,更简洁。
继承class Sub : public Base { ... };class Sub extends Base { ... }Java 使用 extends 明确继承关系。
接口通过纯虚函数的抽象类实现interface MyInterface { ... }
class MyClass implements MyInterface { ... }
Java 的 interface 定义方法签名,类通过 implements 实现接口,避免多继承的复杂性。
多态/虚函数需用 virtual 声明多态函数static 方法默认支持多态,final 修饰可禁止覆盖。Java 默认支持多态,简化设计。
内存管理手动 new/deletenew 分配内存,无需手动释放,由垃圾回收器自动管理。Java 自动内存管理减少错误风险。
数组声明int x[10];int* x = new int[10];int[] x = new int[10];Java 语法更统一,x.length 直接获取长度。
引用赋值MyClass b = a;(对象数据拷贝)MyClass b = a;(引用拷贝,指向同一对象)Java 赋值传递引用而非对象副本。
相等性比较== 默认比较对象内容(需重载运算符)== 比较引用地址,equals() 比较内容。Java 字符串等内容比较必须用 str1.equals(str2)

二、环境安装

安装 JDK (建议 JDK 17 或 21 LTS ) 和一个好用的 IDE(如 IntelliJ IDEA 社区版)

三、 java构建工具

Maven 和 Gradle,它们是 Java 世界的“makefile”,用于管理项目依赖和构建生命周期

四、 了解 Spring

4.1、Spring和Spring boot的关系:

Spring Boot 是基于 Spring 框架构建的,它的出现是为了让你更轻松、更快速地去使用 Spring。它不是要替代 Spring,

Spring 是基础,是提供依赖注入、事务管理等核心能力的框架。它很强大,但配置起来相对繁琐。

Spring Boot 是进化,它站在Spring的肩膀上,通过"自动配置"和"起步依赖"等机制,把这些繁琐都隐藏了起来。

它俩的关系,就像你之前学习的接口和实现类的关系——Spring定义了强大的能力规范,而Spring Boot提供了一个开箱即用、极其便捷的默认实现,让你能更快地投入到业务开发中

4.2、Spring 常用注解

4.2.1、注解与作用对照表
注解作用
@SpringBootApplication主启动类注解,包含自动配置、组件扫描等功能
@RestControllerREST 控制器,返回数据而非视图
@RequestMapping映射 HTTP 请求路径
@GetMapping/@PostMapping分别映射 GET/POST 请求
@Autowired自动注入依赖
@Service/@Repository标记业务层/数据访问层组件
@ConfigurationProperties绑定配置文件属性

使用示例(部分注解)

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@RestController
@RequestMapping("/api")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/users")
    public List<User> getUsers() {
        return userService.findAll();
    }
}
4.2.2、请求映射注解:定义路径和 HTTP 方法

这些注解对应 HTTP 的几种基本操作(CRUD):

注解HTTP 方法用途类似数据库操作
@GetMappingGET获取资源SELECT
@PostMappingPOST创建资源INSERT
@PutMappingPUT更新全部资源UPDATE
@PatchMappingPATCH更新部分资源UPDATE(部分字段)
@DeleteMappingDELETE删除资源DELETE
@RequestMapping通用可以指定多种方法-

这里只是声明,在@DeleteMapping不一定要删除,也可以进行其它操作

示例代码

@RestController
@RequestMapping("/api/users")  // 类级别:所有方法的公共前缀
public class UserController {
    
    // GET /api/users
    @GetMapping
    public List<User> listUsers() {
        return userService.findAll();
    }
    
    // GET /api/users/123
    @GetMapping("/{id}")  // 路径变量
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }
    
    // POST /api/users
    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }
    
    // PUT /api/users/123
    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        return userService.update(user);
    }
    
    // DELETE /api/users/123
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.delete(id);
    }
}
4.2.3、参数绑定注解:从请求中取数据

注解与数据来源对应表

注解数据来源适用场景
@PathVariableURL 路径中的变量RESTful 风格的资源 ID
@RequestParam查询参数(?key=value过滤条件、分页参数
@RequestBody请求体(JSON/XML)提交的复杂数据对象
@RequestHeaderHTTP 请求头认证令牌、浏览器信息等
@CookieValueCookie 数据会话标识、用户偏好设置
@ModelAttribute表单数据(Form 提交)传统 MVC 表单处理

关键说明

  • @PathVariable:适用于动态 URL,如 /users/{id}
  • @RequestParam:常用于 GET 请求,参数显式出现在 URL 中。
  • @RequestBody:需配合 Content-Type: application/json 使用,反序列化为对象。
  • @ModelAttribute:用于绑定表单字段到对象属性,支持多部分表单(如文件上传)。

示例代码

@RestController
@RequestMapping("/api")
public class DemoController {
    
    // URL: /api/users/123?page=1&size=10
    @GetMapping("/users/{userId}")
    public String demo(
        @PathVariable Long userId,           // 从路径取: 123
        @RequestParam int page,               // 从查询参数取: 1
        @RequestParam(defaultValue = "20") int size,  // 带默认值
        @RequestHeader("User-Agent") String ua,  // 从请求头取浏览器信息
        @CookieValue(value = "sessionId", required = false) String sessionId
    ) {
        return "User: " + userId + ", Page: " + page;
    }
    
    // POST /api/users  with JSON body: {"name":"Alice","age":25}
    @PostMapping("/users")
    public User create(@RequestBody User user) {  // 自动解析 JSON 到 User 对象
        return userService.save(user);
    }
}

4.2.4、 响应处理注解

注解作用
@ResponseBody方法返回值直接写入 HTTP 响应体(不经过视图解析器)
@ResponseStatus指定 HTTP 响应状态码

使用说明

  • @ResponseBody
    通常用于 RESTful API 开发,将方法返回的对象(如 JSON 或 XML)直接写入响应体,跳过视图渲染。

  • @ResponseStatus
    可标注在方法或异常类上,强制返回指定的 HTTP 状态码(如 @ResponseStatus(HttpStatus.NOT_FOUND))。

示例代码

@RestController
public class ResponseController {
    
    @GetMapping("/success")
    @ResponseStatus(HttpStatus.OK)  // 返回 200
    public String success() {
        return "OK";
    }
    
    @PostMapping("/create")
    @ResponseStatus(HttpStatus.CREATED)  // 返回 201 Created
    public User create() {
        return new User("Bob");
    }
    
    // 异常处理方法
    @ExceptionHandler(UserNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)  // 返回 404
    public ErrorResponse handleNotFound() {
        return new ErrorResponse("用户不存在");
    }
}
4.2.5、依赖注入注解:管理对象

以下是整理后的表格形式:

注解作用说明
@Autowired自动注入依赖Spring 最常用的注入方式
@ResourceJava 标准的注入按名称注入
@InjectJava 标准的注入按类型注入
@Qualifier指定注入哪个实现当有多个同类型 Bean 时使用

示例代码

@RestController
public class UserController {
    
    // 字段注入
    @Autowired
    private UserService userService;
    
    // 构造器注入(推荐)
    private final OrderService orderService;
    
    public UserController(OrderService orderService) {
        this.orderService = orderService;  // Spring 自动调用
    }
    
    // Setter 注入
    @Autowired
    public void setMailService(MailService mailService) {
        this.mailService = mailService;
    }
}

@Service  // 标记这是一个 Service 组件
public class UserService {
    // 业务逻辑
}

@Repository  // 标记这是一个数据访问组件
public interface UserRepository extends JpaRepository<User, Long> {
    // 数据库操作
}
4.2.6、自定义注解

自定义注解可以可以被读取和处理(传参功能)

// 1. 先定义注解(就像定义标签模板)
public @interface Cacheable {
    String key() default "";
    int ttl() default 3600;  // 过期时间
}

// 2. 在代码上贴标签
@Service
public class UserService {
    
    @Cacheable(key = "user.list", ttl = 1800)  // 贴个标签:这个方法要缓存30分钟
    public List<User> getAllUsers() {
        // 查询数据库...
    }
    
    @Cacheable(key = "user.", ttl = 600)  // 贴标签:缓存10分钟
    public User getUserById(Long id) {
        // 查询数据库...
    }
}

// 3. 写代码读取标签(这才是关键!)
@Aspect
@Component
public class CacheAspect {
    
    // 拦截所有贴了 @Cacheable 的方法
    @Around("@annotation(cacheable)")
    public Object handleCache(ProceedingJoinPoint joinPoint, 
                              Cacheable cacheable) {
        // 读取注解里的值
        String key = cacheable.key();    // 拿到 "user.list"
        int ttl = cacheable.ttl();       // 拿到 1800
        
        // 根据注解的值做不同的处理
        Object result = cache.get(key);
        if (result == null) {
            result = joinPoint.proceed();  // 执行原方法
            cache.put(key, result, ttl);   // 按ttl存缓存
        }
        return result;
    }
}

示例2:多注解组合

// 定义多个注解
public @interface Cache {
    String key();
    int ttl() default 3600;
}

public @interface RateLimit {
    int value();  // 每秒允许次数
    String key() default "default";
}

// 在一个类中使用多个注解
@Service
public class ProductService {
    
    @Cache(key = "product.list", ttl = 1800)
    @RateLimit(10)  // 每秒10次
    public List<Product> getAllProducts() {
        return productRepository.findAll();
    }
    
    @Cache(key = "product.", ttl = 600)
    @RateLimit(value = 5, key = "product.detail")
    public Product getProduct(Long id) {
        return productRepository.findById(id);
    }
}

// 处理器可以同时处理多个注解
@Aspect
@Component
public class ServiceAspect {
    
    @Around("@annotation(cache) && @annotation(rateLimit)")
    public Object handleService(ProceedingJoinPoint pjp,
                                Cache cache, 
                                RateLimit rateLimit) {
        // 从 @Cache 取值
        String cacheKey = cache.key();
        int ttl = cache.ttl();
        
        // 从 @RateLimit 取值
        int limit = rateLimit.value();
        String limitKey = rateLimit.key();
        
        // 组合使用这些值
        // 1. 检查限流
        if (!rateLimiter.tryAcquire(limitKey, limit)) {
            throw new RuntimeException("太频繁了");
        }
        
        // 2. 尝试从缓存获取
        Object result = cacheManager.get(cacheKey);
        if (result == null) {
            result = pjp.proceed();
            cacheManager.put(cacheKey, result, ttl);
        }
        
        return result;
    }
}

自定义注解就是一个传参工具,只不过:

参数不是传给方法,而是贴在代码上

读取不是即时获取,而是通过反射后续读取

用途不是业务逻辑,而是告诉框架/工具怎么处理这段代码

4.2.6、组件标记注解
注解分层含义
@Component通用最基础的组件,标记为 Spring 管理的 Bean
@Service业务层标记业务逻辑类(语义上更明确)
@Repository数据层标记数据访问类(Spring 会自动转换数据库异常)
@Controller控制层标记控制器
完整实战示例(博客系统)
// 1. 实体类
public class Article {
    private Long id;
    private String title;
    private String content;
    private LocalDateTime createTime;
    // getter/setter 省略
}

// 2. 业务层
@Service
@Transactional
public class ArticleService {
    
    @Autowired
    private ArticleRepository articleRepository;
    
    public Article findById(Long id) {
        return articleRepository.findById(id)
            .orElseThrow(() -> new ArticleNotFoundException(id));
    }
    
    public Article save(Article article) {
        article.setCreateTime(LocalDateTime.now());
        return articleRepository.save(article);
    }
}

// 3. 控制器层
@RestController
@RequestMapping("/api/articles")
@CrossOrigin(origins = "http://localhost:3000")  // 允许跨域请求
public class ArticleController {
    
    @Autowired
    private ArticleService articleService;
    
    @GetMapping
    public List<Article> list(
        @RequestParam(required = false) String keyword,
        @RequestParam(defaultValue = "1") int page,
        @RequestParam(defaultValue = "10") int size
    ) {
        // 根据关键词搜索文章
        return articleService.search(keyword, page, size);
    }
    
    @GetMapping("/{id}")
    public Article getOne(@PathVariable Long id) {
        return articleService.findById(id);
    }
    
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Article create(@Valid @RequestBody Article article) {
        return articleService.save(article);
    }
    
    @PutMapping("/{id}")
    public Article update(
        @PathVariable Long id,
        @Valid @RequestBody Article article
    ) {
        article.setId(id);
        return articleService.save(article);
    }
    
    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable Long id) {
        articleService.delete(id);
    }
    
    // 异常处理
    @ExceptionHandler(ArticleNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleNotFound(ArticleNotFoundException ex) {
        return new ErrorResponse(ex.getMessage());
    }
}
总计
注解与角色对照表
注解一句话解释经典比喻
@Controller负责接客,处理HTTP请求饭店门口的迎宾员
@Service负责算账,处理业务逻辑饭店里炒菜的厨师
@Repository负责搬货,操作数据库仓库的搬运工
@Component啥活都干,通用工具类饭店的水电工

说明

  • @Controller:处理用户请求并返回响应,通常与视图层交互。
  • @Service:封装业务逻辑,协调多个数据操作或复杂计算。
  • @Repository:直接与数据库交互,提供数据增删改查功能。
  • @Component:通用组件,用于非特定层但需被Spring管理的类。

注解设计哲学

声明式编程:你只需要声明"是什么",框架负责"怎么做"

约定优于配置:遵循命名规范,减少配置

关注点分离:不同注解处理不同维度的关注点

为什么分这么细?

1. 各司其职,分工明确

前台(Controller)只负责接待,不负责算账

业务部(Service)只负责算账,不负责去仓库搬货

仓库(Repository)只负责搬货,不负责接待

2. 容易找人(维护方便)

页面报错 → 找 Controller

业务逻辑错了 → 找 Service

数据存错了 → 找 Repository

通用功能坏了 → 找 Component

3. 换人不换岗(解耦)
// 今天用MySQL数据库
@Repository
public class UserRepository {
    // 操作MySQL
}

// 明天换MongoDB,只换仓库管理员,业务部不用改
@Repository  
public class UserRepository {
    // 操作MongoDB,对外提供同样的方法
}
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐