乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 Java概述与环境搭建

    • Java概述与环境搭建
    • Java语言概述
    • 解释型语言与编译型语言对比
    • JDK安装与配置
    • JDK、JRE、JVM 详解
    • HelloWorld程序详解
    • IDE 介绍
  • 第2章 标识符与基本数据类型

    • 章节导读
    • 变量概述
    • 常量概述
    • 基本类型与包装类
    • 字节型 byte
    • 短整型 short
    • 整型 int
    • 长整型 long
    • 单精度浮点型 float
    • 双精度浮点型 double
    • 字符型 char
    • 布尔型 boolean
    • 类型转换
  • 第3章 运算符与表达式

    • 章节导读
    • 算术运算符
    • 赋值运算符
    • 关系运算符
    • 逻辑运算符
    • 位运算符
    • 条件运算符
    • 运算符优先级
    • 表达式
  • 第4章 流程控制

    • 章节导读
    • 常见的程序运行流程
    • if-else 选择结构
    • switch 多分支选择
    • while 循环
    • do-while 循环
    • for 循环
    • break 与 continue
  • 第5章 数组

    • 章节导读
    • 一维数组
    • 多维数组
    • Arrays 工具类
  • 第6章 类与对象

    • 章节导读
    • 类与对象
    • 方法定义与调用
    • 构造方法
    • 封装
    • 访问修饰符
    • package 与 import
    • static 关键字
    • this 关键字
    • 参数传递 详解
    • 枚举
    • 成员内部类
    • 局部内部类
    • 静态内部类
    • 匿名内部类
  • 第7章 接口与继承

    • 章节导读
    • 继承
    • super 关键字
    • final 关键字
    • 多态
    • 向上转型与向下转型
    • 抽象类
    • 接口
    • 抽象类与接口对比
  • 第8章 注解

    • 章节导读
    • 注解基础
    • 元注解详解
    • 自定义注解
  • 第9章 常用类

    • 章节导读:Java 常用类
    • Object 类:万类之祖
    • 包装类:基本类型的对象化
    • String:不可变的字符串
    • StringBuffer:线程安全的可变字符串
    • StringBuilder:可变的字符串构建器
    • Math:数学运算工具类
    • Random:伪随机数生成器
    • 大数值运算 详解
    • 日期时间API 详解
  • 第10章 异常机制

    • 章节导读
    • 异常体系与分类
    • try-catch-finally
    • try-with-resources
    • throws 与 throw
    • 自定义异常
  • 第11章 泛型

    • 章节导读
    • 泛型基础
    • 通配符与PECS原则
    • 类型擦除
  • 第12章 集合框架

    • 章节导读
    • 集合框架概述
    • ArrayList
    • LinkedList
    • HashMap 详解
    • LinkedHashMap 详解
    • TreeMap 详解
    • HashSet
    • TreeSet 详解
    • TreeSet 与 Comparable
    • Collections 工具类详解
  • 第13章 IO流

    • 章节导读
    • IO流概述
    • 字节流
    • 字符流
    • 缓冲流
    • 转换流 详解
    • 序列化 详解
    • NIO与Files 详解
    • NIO与Files工具类
  • 第14章 多线程与并发

    • 第十六章 多线程与并发 —— 章节导读
    • 线程基础详解
    • synchronized 详解
    • Lock 与显式锁详解
    • volatile 详解
    • wait 与 notify 详解
    • ThreadLocal详解
    • 原子类详解
    • 并发工具类详解
    • 线程池详解
  • 第15章 反射

    • 章节导读
    • 反射概述与 Class 对象
    • Constructor 与对象创建
    • Field与Method详解
    • 反射应用详解
  • 第16章 JDK8新特性

    • 章节导读
    • Lambda 表达式
    • Stream API 基础
    • Stream API 高级详解
    • Optional 详解
    • 新日期时间API详解
  • 第17章 JDK9-11新特性

    • 章节导读
    • 模块化系统 — Project Jigsaw(JDK 9)
    • var 局部变量类型推断(JDK 10)
    • 集合工厂方法与增强(JDK 9 / 10 / 11)
    • 接口增强:private 方法(JDK 9)
    • Stream API 增强(JDK 9)
    • Optional 增强(JDK 9 / 10 / 11)
    • String 新增方法(JDK 11)
    • HTTP Client 与 Files 增强(JDK 11)
    • 直接运行 Java 源文件 — JEP 330(JDK 11)
  • 第18章 JDK12-17新特性

    • 章节导读
    • Switch 表达式(JDK 12 预览 / JDK 14 正式)
    • 文本块 Text Blocks(JDK 13 预览 / JDK 15 正式)
    • Records 记录类(JDK 14 预览 / JDK 16 正式)
    • 密封类 Sealed Classes(JDK 15 预览 / JDK 17 正式)
    • instanceof 模式匹配(JDK 14 预览 / JDK 16 正式)
    • Switch 模式匹配 — Pattern Matching for switch(JDK 17 预览 / JDK 21 正式)
    • Helpful NPE 与 String 增强(JDK 12 / JDK 14 / JDK 15)
    • Stream 增强(JDK 12 / JDK 16)
    • 日期时间增强 — Day Period 支持(JDK 16)
  • 第19章 JDK18-21新特性

    • 章节导读
    • 虚拟线程(JDK 19 预览 / JDK 20 第二预览 / JDK 21 正式)
    • 序列集合(JDK 21 正式)
    • Switch 模式匹配(JDK 17 预览 / JDK 18 第二预览 / JDK 20 第四预览 / JDK 21 正式)
    • Record 模式匹配(JDK 19 预览 / JDK 20 第二预览 / JDK 21 正式)
    • 未命名模式与变量(JDK 21 预览 / JDK 22 正式)
  • 第20章 JDK 22-25 新特性

    • 章节导读
    • 字符串模板(JDK 22 预览 / JDK 23 第二预览 / JDK 24 第三预览)
    • Stream Gatherers(JDK 22 预览 / JDK 24 第二预览)
    • 隐式声明类与实例方法(JDK 23 预览 / JDK 24 第二预览)
    • 原始类型模式匹配(JDK 24 预览)
  • 附录

    • Java 核心知识点
    • Java SE 专业术语
    • Java特性索引(JDK 8 → 25)

"大翔在技术选型会上把咖啡杯往桌上一顿:'Java,1995年活到现在,全世界的后端都在跑,咱们飞翔科技凭什么不用?'白歌不紧不慢地接话:'关键是Write Once, Run Anywhere——一套代码,Windows开发、Linux部署,不用改。'台下的产品经理孔蓝眼睛亮了:'那我们的'飞翔运动'App后端是不是也能一套搞定?'"

Java语言概述

本章定位

深入理解Java语言的起源、设计哲学、平台体系,以及JDK 8为何成为Java生态的里程碑版本。这是整个Java SE教程的"世界观"文件。


Java的诞生:从一棵橡树到全球语言

历史背景

1991年,Sun Microsystems公司的James Gosling(詹姆斯·高斯林)领导的"Green Project"团队开始研发一种面向消费电子设备(如机顶盒、PDA)的编程语言。最初命名为Oak(橡树),因Gosling办公室窗外的一棵橡树而得名。后来发现Oak已被注册为商标,团队在一次咖啡馆的头脑风暴中,将语言改名为Java——源自印度尼西亚爪哇岛的咖啡。

1995年5月23日,Sun Microsystems在SunWorld大会上正式发布了Java 1.0。伴随着Netscape Navigator浏览器宣布支持Java Applet,Java一炮而红。

关键时间线:

  • 1991年:Green Project启动,Oak语言诞生
  • 1995年:Java 1.0正式发布,"Write Once, Run Anywhere"口号提出
  • 1998年:Java 2发布,分为J2SE/J2EE/J2ME三大平台
  • 2010年:Oracle以74亿美元收购Sun Microsystems
  • 2014年:JDK 8发布——Java历史上最重要的LTS版本
  • 2018年:JDK 11 LTS发布,Java改为半年一个版本

核心人物

人物角色贡献
James GoslingJava之父领导Green Project,设计Java语言
Bill JoySun联合创始人支持并推动Java项目
Patrick NaughtonGreen Project成员参与初始语言设计
Oracle现任维护者2010年收购Sun,继续发展Java生态

核心理念:Write Once, Run Anywhere

"一次编写,到处运行"——这不仅是Java的口号,更是它最根本的设计哲学。

传统语言的跨平台困境

在Java出现之前,C/C++等语言需要针对不同操作系统和CPU架构分别编译:

Java的解决方案:在操作系统和应用程序之间插入一层JVM(Java Virtual Machine,Java虚拟机)。Java源代码被编译为与平台无关的字节码(Bytecode),由各个平台的JVM负责将字节码翻译为本地机器指令。程序员只需写一套代码、编译一次,就可以在任何安装了JVM的设备上运行。

字节码:跨平台的秘密

层次格式可读性可移植性
源代码纯文本 .java人类可读依赖编码和语言版本
字节码二进制 .classJVM可读(可用javap -c反编译查看)跨平台
本地机器码CPU指令机器可读与CPU架构绑定

字节码(Bytecode)是Java实现跨平台的关键中间层。它是一组紧凑的、与CPU架构无关的指令,由JVM解释执行或在运行时通过JIT编译器转换为本地机器码。每个.class文件开头固定为十六进制的CA FE BA BE(魔数),这是Java字节码的身份标识。


三大平台:Java SE / Java EE / Java ME

Java不仅仅是一门语言,而是一个庞大的技术生态。Oracle(及之前的Sun)将其分为三大平台:

平台全称定位典型场景
Java SEStandard Edition核心基础,所有Java开发者的起点桌面应用、命令行工具、基础后端服务
Java EE(现Jakarta EE)Enterprise Edition企业级Web/分布式应用飞翔科技的电商网站、学生管理系统后端
Java MEMicro Edition嵌入式与移动设备早期功能手机、智能卡、物联网传感器

注意:2017年,Oracle将Java EE移交给了Eclipse基金会,并更名为Jakarta EE。但Java SE始终是三者中最核心的部分——无论你将来学EE还是Android,SE的功底决定你的上限。


JDK 8:Java生态的里程碑

为什么JDK 8如此重要?

2014年3月发布的JDK 8是Java历史上首个**LTS(Long-Term Support,长期支持)**版本,也是目前企业中使用最广泛的Java版本(截至2024年,仍有超过40%的生产环境运行在JDK 8上)。其核心新特性深刻改变了Java的编程范式:

新特性说明影响力
Lambda表达式(x, y) -> x + y 简洁函数式写法⭐⭐⭐⭐⭐
Stream API声明式集合操作:list.stream().filter().map().collect()⭐⭐⭐⭐⭐
接口默认方法(default)接口中提供方法默认实现,不破坏已有实现类⭐⭐⭐⭐
接口静态方法(static)接口中定义工具方法⭐⭐⭐
Optional空值安全容器,优雅处理null⭐⭐⭐⭐
新日期时间API(java.time)不可变、线程安全的LocalDate/LocalDateTime等⭐⭐⭐⭐⭐
方法引用(::)System.out::println 简化Lambda⭐⭐⭐⭐

JDK各LTS版本对比

版本发布时间关键意义当前企业占比(估算)
JDK 82014年3月首个LTS,Lambda/Stream革命~40%
JDK 112018年9月模块化成熟、HTTP Client标准~25%
JDK 172021年9月Record/Sealed Class/Pattern Matching~20%
JDK 212023年9月Virtual Thread/Pattern Matching正式~5%(增长中)

本教程选择JDK 8的理由:它是Java函数式编程的起点,绝大多数企业面试基于JDK 8考察Lambda、Stream、并发编程,且向后兼容至JDK 21。掌握JDK 8,你就能读懂和维护80%以上的企业Java代码库。


代码示例

示例一:验证Java跨平台能力

白歌让大翔在不同操作系统上验证同一份Java代码的执行结果一致性。飞翔科技开发环境是Windows,生产服务器是Linux。

/**
 * CrossPlatformDemo.java
 * 演示:同一份Java代码在不同操作系统上的输出完全一致
 * 场景:飞翔科技技术部验证Java跨平台能力
 */
public class CrossPlatformDemo {
    public static void main(String[] args) {
        // 获取当前操作系统信息
        String osName = System.getProperty("os.name");
        String osArch = System.getProperty("os.arch");
        String javaVersion = System.getProperty("java.version");
        String javaVendor = System.getProperty("java.vendor");

        // 飞翔科技公司数据
        String companyName = "广州飞翔科技";

        System.out.println("═══════════════════════════════════");
        System.out.println("   " + companyName);
        System.out.println("   Java 跨平台验证报告");
        System.out.println("═══════════════════════════════════");
        System.out.println("操作系统名称 : " + osName);
        System.out.println("操作系统架构 : " + osArch);
        System.out.println("Java 版本    : " + javaVersion);
        System.out.println("Java 厂商    : " + javaVendor);
        System.out.println("───────────────────────────────────");
        System.out.println("Java 运行时可用处理器数 : " + Runtime.getRuntime().availableProcessors());
        System.out.println("Java 虚拟机最大内存(MB) : " + Runtime.getRuntime().maxMemory() / 1024 / 1024);
        System.out.println("───────────────────────────────────");

        // 跨平台核心验证:以下代码在任何OS上输出完全一致
        int empCount = 12;          // 飞翔科技员工总数
        double revenue = 8888.88;   // 示例数据
        String slogan = "愿你朝华相顾,愿你前程似锦。";

        System.out.println("公司员工总数 : " + empCount);
        System.out.println("示例营收数据 : ¥" + revenue);
        System.out.println("企业寄语     : " + slogan);
        System.out.println("═══════════════════════════════════");
    }
}

Windows 10 运行输出:

═══════════════════════════════════
   广州飞翔科技
   Java 跨平台验证报告
═══════════════════════════════════
操作系统名称 : Windows 10
操作系统架构 : amd64
Java 版本    : 1.8.0_202
Java 厂商    : Oracle Corporation
───────────────────────────────────
Java 运行时可用处理器数 : 8
Java 虚拟机最大内存(MB) : 1820
───────────────────────────────────
公司员工总数 : 12
示例营收数据 : ¥8888.88
企业寄语     : 愿你朝华相顾,愿你前程似锦。
═══════════════════════════════════

CentOS 7 运行输出(业务参数部分完全一致):

═══════════════════════════════════
   广州飞翔科技
   Java 跨平台验证报告
═══════════════════════════════════
操作系统名称 : Linux
操作系统架构 : amd64
Java 版本    : 1.8.0_202
Java 厂商    : Oracle Corporation
───────────────────────────────────
Java 运行时可用处理器数 : 4
Java 虚拟机最大内存(MB) : 910
───────────────────────────────────
公司员工总数 : 12
示例营收数据 : ¥8888.88
企业寄语     : 愿你朝华相顾,愿你前程似锦。
═══════════════════════════════════

注意:操作系统名称、处理器数量、最大内存等环境相关数据会不同,但业务逻辑代码的输出完全一致——这就是"Write Once, Run Anywhere"的本质。

示例二:JDK 8 Lambda表达式初体验

小崔第一次接触Lambda,用它来整理飞翔科技技术部的员工名单。

import java.util.*;

/**
 * TeamListDemo.java
 * 演示:JDK 8 Lambda 表达式 + Stream API 的简洁性
 * 场景:小崔整理飞翔科技技术部员工名单
 */
public class TeamListDemo {
    public static void main(String[] args) {
        // 飞翔科技技术部员工名单(姓名,职位,年龄)
        String[][] techTeam = {
            {"大翔", "CEO/CTO", "32"},
            {"白歌", "架构师", "29"},
            {"小崔", "后端开发", "25"},
            {"黄俪", "前端开发", "24"},
            {"李眉", "运维工程师", "28"},
        };

        System.out.println("═══════════════════════════════════");
        System.out.println("   飞翔科技 · 技术部花名册");
        System.out.println("═══════════════════════════════════");

        // JDK 8 之前:传统 for 循环打印
        System.out.println("\n【传统方式:for-i 循环】");
        for (int i = 0; i < techTeam.length; i++) {
            System.out.println("  " + techTeam[i][0] + " - " + techTeam[i][1]
                    + "(" + techTeam[i][2] + "岁)");
        }

        // JDK 8:Lambda 表达式 + forEach
        System.out.println("\n【JDK 8 方式:Lambda + forEach】");
        Arrays.stream(techTeam)
              .forEach(member -> System.out.println(
                  "  " + member[0] + " - " + member[1] + "(" + member[2] + "岁)"
              ));

        // JDK 8:Stream API 过滤 + 排序(找出30岁以下的员工,按姓名排序)
        System.out.println("\n【JDK 8 Stream:30岁以下青年员工】");
        Arrays.stream(techTeam)
              .filter(member -> Integer.parseInt(member[2]) < 30)
              .sorted(Comparator.comparing(member -> member[0]))
              .forEach(member -> System.out.println(
                  "  " + member[0] + " - " + member[1] + "(" + member[2] + "岁)"
              ));

        System.out.println("\n  愿你朝华相顾,愿你前程似锦。");
        System.out.println("═══════════════════════════════════");
    }
}
运行输出:
═══════════════════════════════════
   飞翔科技 · 技术部花名册
═══════════════════════════════════

【传统方式:for-i 循环】
  大翔 - CEO/CTO(32岁)
  白歌 - 架构师(29岁)
  小崔 - 后端开发(25岁)
  黄俪 - 前端开发(24岁)
  李眉 - 运维工程师(28岁)

【JDK 8 方式:Lambda + forEach】
  大翔 - CEO/CTO(32岁)
  白歌 - 架构师(29岁)
  小崔 - 后端开发(25岁)
  黄俪 - 前端开发(24岁)
  李眉 - 运维工程师(28岁)

【JDK 8 Stream:30岁以下青年员工】
  小崔 - 后端开发(25岁)
  李眉 - 运维工程师(28岁)
  黄俪 - 前端开发(24岁)

  愿你朝华相顾,愿你前程似锦。
═══════════════════════════════════

Java语言的核心特性

特性说明体现
面向对象一切皆对象(除8种基本类型),支持封装/继承/多态/抽象class/interface/extends/implements
跨平台字节码 + JVM 屏蔽底层差异javac → .class → 任意OS运行
强类型每个变量必须先声明类型,编译期类型检查int x = 10; String s = "hello";
自动内存管理JVM通过GC自动回收不再使用的对象无需手动 free/delete
多线程语言级别内置线程支持Thread / Runnable / java.util.concurrent
健壮性编译期检查 + 运行时检查 + 异常处理体系try-catch-finally
安全性字节码校验、类加载器双亲委派、安全管理器沙箱机制
动态性反射机制允许运行时获取类信息并操作对象Class.forName()

核心原理:JIT编译器与执行模式

Java程序的执行并非纯粹的解释执行,而是采用了混合模式(Mixed Mode):

关键阶段:

  1. 解释执行(冷启动):程序启动时,JVM使用解释器逐条执行字节码。这个阶段启动快但执行慢。
  2. 热点探测:JVM统计每个方法的调用次数和循环次数。当达到-XX:CompileThreshold阈值(默认10000次),标记为"热点代码"。
  3. JIT编译:C1编译器(Client Compiler)快速编译,C2编译器(Server Compiler)深度优化。编译结果缓存在Code Cache中。
  4. 直接执行:后续调用直接执行编译后的机器码,性能显著提升。
  5. 逆优化:如果JIT编译时基于的假设不再成立(如类继承层次变化),则回退到解释执行。

这也是Java常被调侃"先慢后快"的原因——预热完成后,JDK 8 Server模式下的性能可以与C++相媲美。


易错场景与面试考点

反例:混淆JDK、JRE和JVM

小崔刚学Java时犯的经典错误:

# ❌ 错误:只装了JRE就想用javac编译
C:\Users\xiaocui> javac Hello.java
'javac' 不是内部或外部命令,也不是可运行的程序或批处理文件。

# 小崔挠头:"我不是装了Java吗?"
# 白歌看了一眼:"你装的是JRE,只能运行java命令,不能编译。"
# 李眉补刀:"也就是只能java Hello.class,不能javac Hello.java。"

原因分析:

JDK = JRE + 开发工具(javac、jar、javadoc等)
JRE = JVM + 核心类库(rt.jar等)
JVM = 字节码执行引擎

所以你装JRE → 有java命令(能运行)但没有javac命令(不能编译)

纠正:从Oracle官网下载JDK 8(而非JRE 8),安装后java -version和javac -version都应该能正常输出。

面试高频题

Q1:Java为什么能跨平台?

Java的跨平台依赖于两点:① Java源代码被编译为与平台无关的字节码(.class文件),而非特定CPU的机器码;② 每个平台都有各自的JVM实现,负责将字节码翻译为该平台的本地机器指令。JVM充当了抽象层,屏蔽了操作系统和硬件的差异。注意:JVM本身不是跨平台的——Windows版JVM和Linux版JVM是不同的程序,但它们向上提供的字节码执行接口是一致的。

Q2:JDK、JRE、JVM三者之间是什么关系?

JDK(Java Development Kit)是Java开发工具包,包含JRE + 编译工具(javac、jar、javadoc)。JRE(Java Runtime Environment)是Java运行环境,包含JVM + 核心类库。JVM(Java Virtual Machine)是Java虚拟机,负责加载和执行字节码。三者的包含关系:JDK ⊃ JRE ⊃ JVM。

Q3:JDK 8为什么被称为Java的"革命性"版本?

JDK 8引入了Lambda表达式和Stream API,使Java从纯面向对象语言转向支持函数式编程范式。此外,新日期时间API(java.time)解决了旧Date/Calendar的线程安全和设计缺陷;接口默认方法/静态方法让接口可进化而无需破坏现有实现。这些特性大幅减少了样板代码,提升了开发效率和代码可读性。在JDK 8之前,一个排序操作可能需要5-7行匿名内部类代码,JDK 8之后一行Lambda即可完成。

Q4:Java与C/C++的本质区别是什么?

① 编译方式:C/C++直接编译为本地机器码,与平台绑定;Java编译为字节码,在JVM上运行。② 内存管理:C/C++手动管理内存(malloc/free或new/delete),容易内存泄漏;Java由JVM的GC自动回收。③ 指针:C/C++支持指针运算,灵活但危险;Java没有指针概念(只有引用),更安全。④ 多重继承:C++支持多继承;Java通过接口实现多继承效果,避免菱形问题。⑤ 平台:C/C++面向特定平台编译;Java一次编译到处运行。


本章小结:Java诞生于1995年,核心理念是"Write Once, Run Anywhere",通过字节码和JVM实现跨平台。三大平台(SE/EE/ME)覆盖从桌面到企业到嵌入式的全场景。JDK 8(2014年发布)是Java生态的里程碑,引入了Lambda表达式和Stream API,至今仍是企业生产环境的主流版本。

上一页
Java概述与环境搭建
下一页
解释型语言与编译型语言对比