Java基础篇一(认识Java,DOS命令,标识符,关键字,数据类型,变量,常量,类型转换,运算符,程序控制结构)
一、认识Java
1.Java的发展历史
| 时间节点 | 核心事件与版本 | 技术/生态意义 |
|---|---|---|
| 1991年 | “Green”项目启动,目标是家用电器 | Java的前身Oak语言诞生,为智能家电设计。因市场不成熟,项目一度濒临取消。 |
| 1995年 | Java 1.0正式发布(1996.1.23) | 口号 “Write Once, Run Anywhere” 随互联网兴起而引爆。关键突破:Applet 让网页“动”起来。 |
| 1998年 | Java 1.2 (J2SE 1.2) 发布 | J2SE/J2EE/J2ME “三分天下”战略形成,确立了从服务器到嵌入式设备的全方位野心。首次引入 Swing GUI工具包和集合框架。 |
| 2004年 | J2SE 5.0 (Java 5) 发布 | 语言层面的一次革命性更新。引入泛型、注解、自动装箱/拆箱、枚举、增强for循环、可变参数等,深刻改变了Java编码方式。 |
| 2006年 | Java SE 6 发布 | 版本命名去“2”(J2SE→Java SE)。在性能(编译器、JVM)和桌面(脚本引擎、Swing)方面大幅增强。同年,Sun开源Java,形成OpenJDK。 |
| 2009年 | Oracle收购Sun | 以74亿美元完成收购,获得Java所有权。此举在社区引发对Java未来开放性的长期担忧。 |
| 2011年 | Java SE 7 发布 | 在Oracle治下首个主要版本。引入try-with-resources、NIO.2、钻石操作符、Fork/Join框架等。 |
| 2014年 | Java SE 8 (LTS) 发布 | 继Java 5后又一里程碑。Lambda表达式、Stream API、新日期时间API 的引入,将Java带入了现代函数式编程的大门。 |
| 2017年 | Java SE 9 发布 | 最大特性是引入了备受争议的 JPMS模块化系统(Project Jigsaw)。同时,发布周期改为每六个月一次。 |
| 2018年 | Java SE 11 (LTS) 发布 | 重要的LTS版本。HTTP Client API标准化,移除Java EE和CORBA模块,OpenJDK与Oracle JDK在功能上完全一致,但Oracle对商用收费。 |
| 2021年 | Java SE 17 (LTS) 发布 | 最新的LTS版本,密封类、模式匹配等特性稳定,进一步巩固了现代Java语法。社区生态全面转向8/11/17。 |
| 2023年 | Java SE 21 (LTS) 发布 | 引入革命性的 虚拟线程,旨在显著提升高并发应用的吞吐量和简便性,标志着Java并发模型的新时代。 |
1.2 Java的技术体系
1.Java SE(Platform Standard Edition,java平台标准版):
- java技术的基础和核心,是标准版的java开发平台。
- 主要用于开发桌面应用程序
- Java EE(Java 2 Platform,Enterprise Edition,java平台企业版):
- 用于企业级应用及服务开发的,企业版的java平台。
- 开发面向Internet的应用程序 Java Web
- Java ME(Java 2 Platform Micro Edition,java平台微型版):
- 为嵌入式电子设备提供的高度优化的,微缩版的java平台。
- 开发运行于智能设备的程序
1.2.1 关键转折与生态变化
- “三分天下”战略的兴衰
- 初衷:J2SE(标准版)、J2EE(企业版)、J2ME(微型版)旨在覆盖所有计算领域。
- 演变:移动互联网时代,Android(基于Java语法)取代了J2ME;云原生时代,轻量级框架(如Spring Boot)取代了笨重的J2EE应用服务器。如今,“Java EE”已由Eclipse基金会接管并更名为 Jakarta EE。
- 开源与收购:控制权的博弈
- OpenJDK的诞生(2006):Sun的开源决定是Java保持活力的关键,形成了由Oracle、IBM、Red Hat等公司共同维护的生态。
- Oracle收购的影响:Oracle的商业策略(如对JDK收取商业支持费)直接催生了更多下游发行版的繁荣,例如:
- Adoptium/Eclipse Temurin:社区主导,提供免费、高质量的LTS版本。
- Amazon Corretto、Microsoft Build of OpenJDK、Alibaba Dragonwell:云厂商的优化版本。
- 结论:开发者今天应选择 OpenJDK的免费下游发行版,而非Oracle的商用JDK,除非需要官方的商业支持。
- 现代Java的挑战与革新
- 挑战:曾因“臃肿、缓慢”受诟病,面临C#、Go、Python等语言的竞争。
革新
- 语法现代化:从Java 8的Lambda到后续的Records、Pattern Matching,语言更简洁。
- 性能飞跃:JVM的JIT即时编译、G1/ZGC/Shenandoah等垃圾回收器的演进,使性能媲美甚至超越C++。
- 并发革命:Project Loom 推出的虚拟线程,是应对高并发场景的划时代解决方案。
- 云原生适配:通过GraalVM 实现原生镜像编译,极大减少了启动时间和内存占用,完美契合容器化微服务。
1.2.2 总结:Java历久弥新的核心
Java历经近三十年而不衰,其核心优势在于:
- 跨平台与稳定性:JVM“一次编写,到处运行”的承诺依然坚固,是企业级应用的基石。
- 强大的生态:拥有全球最丰富的开源库和框架(如Spring生态),以及最庞大的开发者社区。
- 持续演进:语言和JVM始终保持积极、稳健的现代化步伐。
- 对于开发者的启示是:拥抱变化,理解原理。掌握Java不再仅仅是学习语法,更要理解JVM、现代并发模型和云原生趋势,并关注由OpenJDK社区驱动的免费LTS发行版。
- Java的故事是一部从嵌入式设备出发,意外征服互联网,进而通过持续自我革新奠定企业级和云原生基础的技术史诗。
1.3 Java语言的特点
- 面向对象(OOP)
- 跨平台(操作系统)
- 安全性健壮性
- 没有指针操作
- 垃圾自动回收机制
- 多线程
- 分布式
Java的设计目标明确:“简单、面向对象、分布式、健壮、安全、体系结构中立、可移植、高性能、多线程和动态”。以下特点正是这些目标的具体体现。
| 特点 | 核心解读 | 技术实现/表现 |
|---|---|---|
| 面向对象 纯粹的OOP语言(除基本类型外)。 | 强制以对象和类来组织程序,封装、继承、多态是其基石。 | 所有代码都定义在类中。单根继承(Object类),通过接口实现多继承。 |
| 跨平台/可移植 “一次编写,到处运行”。 | 这是Java最著名的口号,也是其成功的核心。 | JVM是核心。Java源码编译成与平台无关的字节码(.class文件),由各平台特定的JVM解释/编译执行。 |
| 健壮性与安全性 | 设计目标之一是构建可靠的、防崩溃的软件。安全性从语言设计和运行时多层次保障。 | 无指针、强类型检查、自动内存管理、异常处理机制、字节码验证、安全管理器。 |
| 内存自动管理 | 程序员无需手动申请/释放内存,由JVM的垃圾回收器自动回收无用对象,杜绝内存泄漏(但需正确使用)。 | GC算法(如分代收集)自动在后台运行,回收堆内存中不可达的对象。 |
| 多线程支持 | 语言级内置支持,使得并发编程比其他语言(如C)更简单、更统一。 | 提供 Thread 类、Runnable 接口及 synchronized 关键字,以及强大的 java.util.concurrent 并发包。 |
| 分布式支持 | 适合网络应用开发,能够方便地处理TCP/IP协议,进行远程方法调用。 | 早期有 RMI,现在常通过基于TCP/IP的Web服务(如RESTful API)实现。网络API是标准库的核心部分。 |
| 编译与解释结合 | 并非纯解释型语言,结合了编译的高性能和解释的灵活性。 | .java -> 编译 -> .class(字节码) -> JVM解释/即时编译 -> 机器码。现代JVM(HotSpot)的JIT编译器是关键。 |
| 动态性 | 在运行时可以加载新类、获取类型信息、调用方法,支持反射和代理。 | 反射API 允许程序在运行时检查或修改其自身的行为,这是许多框架(如Spring)实现的基础。 |
1.3.1 特点背后的权衡与演进
1.“没有指针”的真相与代价
- 真相:Java有指针,但屏蔽了指针的复杂操作。所有对象变量本质上都是引用(一种受限制的、安全的指针)。你不能直接操作内存地址,不能进行指针运算(如 p++)。
- 代价:牺牲了部分底层控制的灵活性和极致性能(如直接内存操作),换来了安全性和开发效率。对于需要底层操作的情况,提供了 Unsafe 类(慎用)或通过JNI调用本地代码。
- “跨平台”的现代含义与挑战
- 现代含义:跨平台已从桌面扩展到服务器、移动端(Android)、大数据、物联网等全领域。Docker容器化进一步巩固了“一次构建,到处运行”。
- 挑战:“一次编写,到处运行”并非绝对。仍需注意文件路径分隔符、字符编码、字体、特定API等细微差异。GraalVM原生镜像技术正在尝试将Java提前编译为特定平台的可执行文件,以牺牲一点“随处”换启动速度和内存开销。
- “垃圾回收”是双刃剑
- 优势:杜绝大部分内存泄漏,提升开发效率。
- 复杂性:
- Stop-The-World:GC时可能导致应用暂停,影响实时性。
- 调优复杂:需要根据应用特点(如高吞吐、低延迟)选择并调优GC算法(如G1、ZGC、Shenandoah)。
- 内存泄漏依然可能:如果对象被无意持有(如放入静态Map),GC无法回收。
1.4 Java程序的运行机制
1.4.1 JVM与跨平台
Java程序不是直接在操作系统之上运行,而是运行于JVM(java虚拟机)之上。
针对不同的操作系统开发相应的JVM,Java程序运行于不同的JVM之上,因此Java程序可以在不同修改的情况下运行于不同的操作系统之上,从而实现了所谓的跨平台。
Java源代码(.java文件)经编译器编译成字节码(.class文件)字节码文件是计算机可识别的二进制文件,JVM本质上就是一个负责解释执行Java字节码的程序。
JVM执行Java程序的过程:
- 加载.class文件
- 管理并分配内存
- 执行垃圾收集
1.4.2 跨平台原理的深度剖析:三层抽象模型
1 .统一规范层:由 《Java虚拟机规范》 和 《Java语言规范》 定义。这是所有JVM和Java编译器都必须遵守的法律文件,确保了字节码指令集和核心类库行为的一致性。
2. 中间字节码层:.class 文件。这是 “Write Once” 的产出物,也是JVM的输入。它是平台无关的二进制指令集。
3. 本地实现层:各厂商为不同操作系统(Windows, Linux, macOS)和硬件架构(x86, ARM)开发的 JVM具体实现(如HotSpot, OpenJ9)。它们负责将统一的字节码“翻译”成本地系统能理解的指令,即 “Run Anywhere” 的最终执行者。
4.
这三层架构确保了Java程序的跨平台能力,其具体流程如下图所示:
关键点:真正的“跨平台”指的是字节码跨平台,而非源代码。只要目标平台有符合规范的JVM实现,同一个 .class 文件就能运行。这正是Java Applet当年能在各种浏览器中运行的原因。
1.4.3 JVM的核心职责与内部架构
JVM远不止一个“解释器”,它是一个完整的微型操作系统,负责管理Java程序运行的整个生命周期和资源。
- 核心职责扩展
- 类加载:加载 .class 文件,其背后是双亲委派模型的类加载器子系统(Bootstrap, Extension, Application)。
- 内存管理:
- 方法区:存储类结构、常量、静态变量(JDK 8+为元空间)。
- 堆:所有对象实例和数组分配的地方,是GC的主要区域。
- 虚拟机栈:存储栈帧,每个方法调用对应一个栈帧,内含局部变量表、操作数栈等。栈内存由系统自动分配释放。
- 程序计数器:当前线程执行的字节码行号指示器。
- 本地方法栈:为Native方法服务。
- 字节码执行:现代JVM(如HotSpot)采用 “解释器 + JIT即时编译器”的混合模式。热点代码(被频繁执行的方法)会被JIT编译成本地机器码,大幅提升性能。
- 垃圾收集:自动管理堆内存,是Java健壮性的关键。GC需要解决三个核心问题:
- 哪些内存需要回收?(对象是否存活的判定算法:引用计数、可达性分析)
- 什么时候回收?(GC触发时机)
- 如何回收?(各种GC算法:标记-清除、复制、标记-整理,以及对应的收集器:Serial, Parallel, CMS, G1, ZGC, Shenandoah)。
- JVM架构总览图
为了更好地理解各部分如何协作,下图展示了JVM的主要子系统及其关系:
1.4.4 超越传统:现代Java的跨平台演进
当前,Java生态正在发生重要演进,旨在解决传统模型的某些不足:
- 挑战:启动速度与内存占用
- 传统模型问题:JVM需要预热,JIT编译需要时间,导致短期运行的任务(如云函数、CLI工具)启动慢、内存开销大。
- 解决方案:GraalVM与原生镜像
- GraalVM:一种高性能的通用虚拟机,能运行多种语言(Java, JavaScript, Python等),其核心是新的JIT编译器。
- Native Image:GraalVM提供的提前编译技术。它将Java字节码、所依赖的库和一个小型的运行时(SubstrateVM)一起,提前编译成独立的、平台相关的原生可执行文件。
- 优势:启动速度是毫秒级,内存占用极低,非常适合云原生和微服务场景。
- 代价:编译时间较长,运行期失去了部分动态特性(如反射、动态类加载需要额外配置)。这可以看作是用“一次编译,到处运行”的模型,对传统“一次编写,到处运行”模型的补充和优化。
1.4.5 JVM,JRE,JDK
- JVM:Java虚拟机,是核心的运行时引擎,负责执行字节码。单独一个JVM无法开发或运行大多数Java程序。
- JRE(Java RuntimeEnvironment):Java运行时环境(JVM+类库):包含了Java程序运行所需要的JVM及Java核心类库和支持文件,但并不包括Java开发工具(例如编译器)
- JDK的全称:Java Development kit :提供了编译,运行Java程序所需的各种工具和资源,它包括Java的运行环境、Java开发工具和类库,JDK包含Jre,Jre中包含JVm
1.5 Java的开发环境
1.5.1 Path
- 作用或目的:在任意路径下能够直接执行命令
1.5.2 环境变量
- 环境变量是用来指定操作系统运行环境的变量
- Path环境变量:指定可执行文件的搜索路径,也就是可执行文件在本地的存放路径
- ClassPath环境变量:指定字节码文件的搜索路径
- OS环境变量:操作系统的名字
- Date环境变量:当前日期
- TIME环境变量:当前时间
1.5.3配置Java环境变量
1.此电脑->属性->高级系统设置->环境变量
设置目的(原理):告诉windows执行Java命令是从哪个本地文件读取(运行)可执行程序
2.环境变量配置好之后,便可以在全局实用java命令
3.Win+R+输入cmd 可打开DOS命令窗口,输入Javac可检测Java的环境变量是否配置成功
1.6 Java代码的编译、加载和运行
- 编写源文件(源文件.java)
- 使用javac命令编译源文件生成.class文件
- 使用java(虚拟机用于解释字节码文件)命令运行.class文件输出程序结果
- 编译:编译器对源代码的语法进行检查,生成字节码文件
- 运行:JVM执行变成生成的字节码
- 源文件与class文件:在Java中源文件的名称必须是文件中主类的名称,扩展名必须为.java。源文件中可以包含多个类,但是最多只能有一个类使用public修饰,使用public修饰的类就是主类。在Java中,源文件还被作为编译单元,即一个源文件就是一个编译单元。编译器会为源代码中的每个类生成一个.class文件,.class文件的名称是类的名称,扩展名为.class。
1.7 Main方法
- 方法名:只能是main,不能是Main等形式。
- 修饰符:public static void 三个缺一不可,多一个不行
- 参数:
- 参数类型为字符串数组 String[]
- 参数名称只要符合Java中标识符命名要求即可
- 参数声明的两种方式:String[] args, 或 String args[]
1.8 Java的编码规范(初学者简版)
- 类的命名,采用以大写字母开头的大小写字符间隔的方式即(大驼峰式命名法)。
- 一行只写一条语句
- 块缩进符合每开始一个新块缩进一个制表符
- 对于块状结构 左大括号前不换行 左大括号后换行 右大括号前换行
1.9 Java命令
- javac //后跟文件名称,需要包含扩展名.java
- javac -d //指明存放字节码文件(class)文件的位置
- java //后跟类名
- javadoc //生成注释文档
2、DOS命令
- E: 表示直接进入指定盘符
- CLS:清除屏幕
- DIR:列出目录清单
- cd 命令
- cd…回到上级目录
- cd 指定目录名 可进入指定目录
- cd \ 返回当前盘符的目录下
- cd /d E:\workspace 可进行盘符切换并进入到指定目录下 不加/d不能改变盘符
3、标识符,关键字,数据类型
3.1 注释
- 注释的三种形式:单行注释、多行注释、文档注释
- 文档注释(documentation comment)以“/**”开始,以“*/”结束。使用文档注释可以将关于程序的信息嵌入到程序自身中。
- javadoc命令可以文档注释中的内容提取出来,将其放入到一个HTML文件中。文档注释方便了程序的文档化。
3.2 分隔符、代码块
- 每行功能代码以 ‘;’ 作为结束符号
- 空格没有实际意义,可以利用空格无意义,将代码合理缩进,易读
- {}包含的代码称之为代码块, 例如类if(){}、方法{}、类{}等等
3.3 标识符
- 作用:标识符是用于给类、方法、变量、包和接口命名的,由字母、数字、_和$组成且首字母不能是数字的字符序列。
- 概念:Java中类、方法和变量的名称,称之为标识符
- 注意事项:
- 标识符的长度没有限制
- Java是大小写敏感的,所有标识符区分大小写 main Main
- 不能使用Java的关键字和保留字
- 命名规范:
- 英文字母、数字、下划线、美元符号组成
- 首字母不能是数字
- 不能使用Java关键字
- 不能使用true、false和null三个字面量
3.4 关键字
1.Java保留了const和goto关键字,但是没有使用。Java还保留了下面这些关键字:true、false和null。这些关键字是Java定义的数值。
2.Return 关键字
- 如果方法的返回类型为void,可以使用return跳出方法,但是不能使用return返回数据。
- 可以用于在方法中进行结果返回
3.5 数据类型
注意:
基本数据类型也可以分成两大类:数值型、布尔型
通俗的理解编写代码的工作包括:定义变量,保存数据,进行处理(计算)
基本类型与引用类型的区别:
- 基本类型:变量保存实际的数据。
- 引用类型:变量不包含实际的数据,而是包含实际数据在内存中的位置。
3.5.1 基本数据类型
- 整形
- 浮点型
- 字符型
(1)char是16位,Java在内部使用16位的整数表示字符(Unicode编码),char类型的范围0~65535。//全世界基本的语言符号基本都包含了
(2)char也可以用作整数类型,可以将整型字面值赋给char类型的变量,可以在char类型上执行算术运算。
(3)26个小写字母、26个大写字母、以及10个数字0-9,其编码是连续的。 - 布尔型
4、 变量和常量
- 变量:变量表示存储单元,变量名就是存储单元的名称,变量初始化之后就可以通过变量名访问存储单元
- 常量:声明常量需要使用final关键字,量通常在声明时赋值,并且赋值之后其值不能改变常量标识符通常全部为大写
- 变量的分类:根据变量声明的位置,变量可以分为实例变量和局部变量
- 实例变量:在类的{}内直接定义的变量,称为实例变量或成员变量,作用范围:整个类中都可以使用,实例变量在创建对象时会自动初始化,并有初始值(默认值)。基本数据类型皆对应各自的默认初始值,引用数据类型默认初始值为Null
- 局部变量:在方法中或代码块{}中定义的变量,称之为局部变量,作用范围:直接包含它的{}内有效,局部变量不会自动初始化,没有默认值,使用之前必须要初始化。
5、类型转换
- 类型转换是从一种数据类型到另一种数据类型的转换
- 基本数据类型:自动类型转换(隐式类型转换)是指兼容的两种数据类型自动由低级向高级的类型转换 强制类型转换(显式类型转换)是指高级类型向低级类型的类型转换,这种转换可能会损失精度或者溢出
- 引用数据类型:向上转型和向下转型
- 基本数据类型和引用数据类型之间:自动装箱和自动拆箱
6、运算符
计算机编程语言用运算符来模拟数学中的运算符号。
- 按操作数数运算符可分类为单目运算符、双目运算符、三目运算符
- 按功能分运算符可分类为赋值运算符、算术运算符、比较运算符、逻辑运算符、位运算符、条件运算符、其他运算符
6.1 算数运算符
6.1.1 自增和自减运算符
- 自增运算符:++
- 自减运算符:–
- 执行原理:++i 先自身加1,再执行操作 i++先执行操作,再自身加1
- 注意点:
- 案例:
6.1.2 +号作为字符串连接符
在实际代码的应用中,+号如果和字符串类型的数据进行使用,表示字符串连接符,意指字符串拼接。只要有一个字符串(String)类型的数据,使用+号时,+号就是用于字符串连接。
6.2 赋值运算符
- 概念:赋值运算符是将右边表达式的运算结果赋值给左侧变量的运算符
- 延伸:
6.3 比较运算符
- 概念:比较运算符是用来判断两个表达式或值大小关系的运算符
- 延伸:
6.4 逻辑运算符
- 概念:逻辑运算符是将逻辑值进行与、或、非操作的运算符
- 延伸:
6.5 条件运算符
- 概念:三目或三元运算符,对三个操作数进行操作的运算符
- 语法:逻辑表达式 ? 表达式1:表达式2
- 执行原理:逻辑表达式结果为true时,返回表达式1,逻辑表达式结果为false时,返回表达式2
- 逻辑图:
6.6 位运算符
1.概念:位运算符是直接对数值在内存中的二进制位进行操作的运算符
2.延伸:
6.6.1 位运算符的应用
有符号数左移(<<)
有符号数右移(>>)
无符号数右移(>>>)
6.7 其他运算符
7、运算符的优先级
8、表达式
1.概念:表达式是由操作数和运算符组成,执行指定计算并返回确定值的式子。
9、程序控制结构
1.概念:程序控制结构式结构化程序设计中用于控制程序执行顺序的逻辑结构
2.延伸:程序控制结构分为顺序结构,选择结构,循环结构。
9.1 顺序结构
顺序结构是在程序中按照指令的先后顺序,逐条执行的程序控制结构
- 特点:按照代码的先后顺序、依次逐条执行
9.2 选择结构
- 概念:选择结构是根据条件判断结果,决定程序后续执行顺序的程序控制结构
- 分类:if选择结构,switch选择结构
- if选择结构分为:单分支if判断,if-else双分支判断,if-else-else if 多分支判断
- if结构中可以嵌套if选择结果,三种if结构可以灵活嵌套和灵活使用。
- switch选择结构:是利用swtich和case进行等值判断的多分支选择结构
switch结构和多重if选择结构的对比
9.3 循环结构
- 概念:循环结构是反复执行一系列指令直到某些特定条件满足的基本程序控制结构。
- 循环结构的三要素:循环变量,循环条件,循环体。
- 循环结构的分类:while循环,do-while循环,for循环。
- 循环结构在具体使用中可以根据实际场景和各自循环的特点进行使用,同时在使用时可以使用单一循环结构,也可以对循环结构进行组合嵌套使用。
9.3.1 while循环
- 特点:先判断,再执行。
- 代码示意:
- 执行逻辑图:
- 注意事项:使用循环结构时,要避免死循环。所谓的死循环,就是永远不会提出的循环称为死循环。
9.3.2 do-while
- 特点:先执行,后判断
- 代码示意:
- 执行逻辑图:
- while和do-while的区别
9.3.3 for循环
- 特点:for循环是一种常用于循环次数明确操作的循环结构
- 代码示例:
9.4 控制结构中的关键字
- continue:在循环结构中,用于跳过本次循环
- break:在switch控制结构中,break用于跳出switch语句,在循环结构中,用于跳出循环
