JAVASE查漏补缺
这段时间学习了很多知识,好多还有疑问不清楚的地方。今天有空总结一下。
javame,javase,javaee
一、Java ME(Micro Edition,微型版)
Java ME是一种适用于移动设备和嵌入式系统的小型Java平台,具有高度可移植性和跨平台性,并提供丰富的API库和工具来简化应用程序开发。比如在按键机里的java小游戏。随着智能手机(iOS/Android)的普及,Java ME 逐渐被淘汰。
二、Java SE(Standard Edition,标准版)
Java 的基础版本,面向桌面应用和通用软件开发,是其他 Java 版本的基础。包含 Java 核心类库(如 java.lang
、java.util
、java.io
等)、图形界面工具包(Swing/AWT)、网络编程(Socket)等。开发工具:IntelliJ IDEA、Eclipse、NetBeans。持续更新,是 Java 生态的基石。
-
技术栈:
- 核心技术:多线程、IO/NIO、反射、集合框架、JDBC(数据库连接)等。
- 开发工具:IntelliJ IDEA、Eclipse、NetBeans。
三、Java EE(Enterprise Edition,企业版)→ 现更名为 Jakarta EE
原由 Oracle 主导,用于开发大型企业级应用(如分布式系统、Web 服务、电商平台、金融系统等)。基于 Java SE,提供一套企业级开发规范(如 Servlet、JSP、EJB、JPA、JMS、WebSocket 等),解决分布式事务、安全性、高并发等复杂场景问题。
技术栈(Jakarta EE 核心规范):
- Web 层:Servlet、Jakarta Server Pages(JSP)、Jakarta Faces(JSF)、WebSocket。
- 业务层:Enterprise JavaBeans(EJB)、CDI(上下文和依赖注入)。
- 数据层:JPA(Java Persistence API,ORM 规范)、JDBC。
- 分布式与集成:JMS(消息队列)、JAX-RS(RESTful Web 服务)、JAXB(XML 绑定)。
- 容器支持:需要运行在应用服务器中(如 Tomcat、WildFly、GlassFish、WebSphere、WebLogic)。
三者对比
维度 | Java ME | Java SE | Jakarta EE(原 Java EE) |
---|---|---|---|
目标场景 | 嵌入式设备、移动设备(旧) | 桌面应用、控制台程序 | 企业级应用(Web、分布式系统) |
依赖关系 | 基于 Java SE 精简 | 基础版本 | 基于 Java SE,扩展企业功能 |
核心技术 | MIDP、CLDC、移动图形库 | 核心类库、Swing/AWT | Servlet、JPA、EJB、JMS 等规范 |
运行环境 | 小型设备虚拟机(KVM) | 标准 JVM | 应用服务器(如 Tomcat、WildFly) |
现状 | 已淘汰,仅遗留系统 | 持续更新,生态核心 | 转型云原生,标准化企业开发 |
javac
javac
是 Java 编译器,用于将 Java 源代码(.java
文件)编译为字节码(.class
文件),以便在 Java 虚拟机(JVM)上运行。它是 Java Development Kit (JDK) 的核心组件之一。
jdk版本 8 ,16,17,21
版本 | 发布时间 | 特性亮点 | 支持状态 | 适用场景 |
---|---|---|---|---|
JDK 8 | 2014-03 | Lambda 表达式、Stream API、日期 API | LTS(长期支持至 2030-12) | legacy 系统、稳定性优先的企业应用 |
JDK 16 | 2021-03 | 模式匹配、Record 类、Vector API | 非 LTS(支持至 2022-09) | 尝鲜新特性,不建议生产环境 |
JDK 17 | 2021-09 | 密封类、强封装 JDK 内部 API | LTS(长期支持至 2029-09) | 企业级应用、云原生开发 |
JDK 21 | 2023-09 | 虚拟线程、分代 ZGC、字符串模板 | LTS(长期支持至 2031-09) | 高性能、高并发应用 |
jdk目录
jdk-<版本号>/
├── bin/ # 可执行程序(开发工具)
├── conf/ # 配置文件
├── include/ # C/C++ 头文件(用于JNI开发)
├── jmods/ # JMOD 模块文件(Java 9+ 模块化系统)
├── legal/ # 许可证文件
├── lib/ # 工具库文件
└── release # JDK 版本信息
1. bin/
- 开发工具
包含编译器、调试器、运行工具等可执行程序:
javac
:Java 编译器,将.java
源码编译为.class
字节码。java
:Java 应用程序启动器,运行.class
或 JAR 文件。jar
:JAR 文件打包工具,用于创建和管理 JAR 归档。jdb
:Java 调试器,用于调试 Java 程序。javadoc
:文档生成工具,从源码注释生成 API 文档。jconsole
:可视化监控工具,查看 JVM 性能和资源使用。jlink
:Java 9+ 新增,用于创建自定义运行时镜像。jmod
:Java 9+ 新增,操作 JMOD 模块文件。
2. conf/
- 配置文件
存放 JDK 和 JRE 的配置:
security/
:安全相关配置(如java.security
)。logging.properties
:Java 日志系统配置。net.properties
:网络相关配置(如代理设置)。
3. include/
- C/C++ 头文件
用于 JNI(Java Native Interface) 开发,允许 Java 调用本地 C/C++ 代码:
jni.h
:JNI 核心头文件。jni_md.h
:平台相关的 JNI 头文件(如 Windows/macOS/Linux 不同实现)。
4. jmods/
- JMOD 模块文件(Java 9+)
Java 9 引入的模块化系统,每个 .jmod
文件包含:
- 模块的类文件、资源、配置。
- 模块描述符
module-info.class
。 - 本地库和命令行工具(如
java.base.jmod
)。
5. lib/
- 库文件
存放 JDK 工具依赖的库和资源:
tools.jar
:开发工具(如javac
)的实现类。jrt-fs.jar
:Java 运行时文件系统,用于访问 JMOD 文件。src.zip
:Java 标准库的源代码(如java.util
、java.io
)。jvm.cfg
:JVM 配置文件,指定可用的 JVM 实现。
6. legal/
- 许可证文件
包含各模块的开源许可证信息(如 java.base
的许可证)。
7. release
- JDK 版本信息
文本文件,记录 JDK 版本、构建信息和依赖关系:
编辑环境变量为什么分两步先配置java_HOME 再配置path
统一引用: PATH中的路径一般不进行修改。
若直接在 PATH
中写死 JDK 路径(如 C:\Program Files\Java\jdk-17\bin
),当需要切换 JDK 版本时,需同时修改 PATH
中的所有路径,容易出错。
灵活切换版本:通过修改 JAVA_HOME
的值,无需改动 PATH
,即可快速切换 JDK 版本。
String,StringBUffer,StringBuilder
String
类是 Java 语言的核心类之一,位于 java.lang
包 下。该包是 Java 语言的基础,无需显式导入即可直接使用。StringBuffer
和 StringBuilder
是 Java 中用于 高效处理可变字符串 的类,它们弥补了 String
类不可变的缺陷。
特性 | StringBuffer | StringBuilder |
---|---|---|
线程安全 | 同步(所有方法有 synchronized ) | 非同步(性能更高) |
诞生版本 | JDK 1.0 | JDK 1.5(为优化 StringBuffer 引入) |
适用场景 | 多线程环境(如 Web 应用) | 单线程环境(如工具类、局部变量) |
性能 | 略低(同步开销) | 更高(无同步开销) |
共同特性
-
可变字符串:
与String
不同,StringBuffer
和StringBuilder
的内容可动态修改,无需创建新对象。 -
相同 API:
两者方法签名几乎完全一致,
append() // 追加内容
insert() // 插入内容
delete() // 删除指定位置字符
replace() // 替换字符
reverse() // 反转字符串
capacity() // 获取容量(非长度)
ensureCapacity() // 确保容量至少为指定值
注释
单行注释、多行注释 和 文档注释
一、单行注释(//)
- 语法:以
//
开头,直到行末结束。 - 用途:解释单行代码或添加简短说明。
二、多行注释(/* ... */)
- 语法:以
/*
开头,以*/
结束,可以跨越多行。 - 用途:注释较长的代码块或暂时禁用代码。
三、文档注释(/ ... /)*
- 语法:以
/**
开头,以*/
结束,支持特殊标签(如@param
、@return
)。 - 用途:生成 API 文档(如 JavaDoc),供开发者参考。
强制转换,自动转换
类型转换(Type Casting) 是将一种数据类型转换为另一种数据类型的过程。根据转换方式的不同,可分为 自动转换(隐式转换) 和 强制转换(显式转换)。
一、自动转换(隐式转换)
1. 概念
- 无需显式声明,编译器自动完成。
- 小范围类型 向 大范围类型 转换(安全转换,不会丢失数据)。
2. 转换规则
byte → short → int → long → float → double
char → int
3. 示例
// 整型转浮点型
int num = 10;
double d = num; // 自动转换:int → double,d = 10.0// 字符转整型
char c = 'A';
int ascii = c; // 自动转换:char → int,ascii = 65// 多种类型混合运算
byte b = 5;
int i = 10;
float f = 3.14f;
double result = b + i + f; // 结果为 double 类型
二、强制转换(显式转换)
1. 概念
- 需要显式使用语法:
(目标类型) 值
。 - 大范围类型 向 小范围类型 转换(可能丢失数据,需谨慎)。
2. 转换规则
double → float → long → int → short → byte
int → char
3. 示例
// 浮点型转整型(截断小数部分)
double d = 3.99;
int i = (int) d; // 强制转换:double → int,i = 3(小数部分丢失)// 大范围整型转小范围整型(可能溢出)
long l = 1000L;
short s = (short) l; // 强制转换:long → short,s = 1000(在 short 范围内)long big = 3000000000L;
int small = (int) big; // 溢出:small = -1294967296(数据错误)// 整型转字符(根据 ASCII 码转换)
int code = 65;
char c = (char) code; // 强制转换:int → char,c = 'A'
逻辑运算符
一、基本逻辑运算符
&(且)运算符:运算符两边只要有 false 则结果为 false,
|(或)运算符:运算符两边只要有 true 则结果为 true,
^(异或)运算符:运算符两边同为 false 或 true 则结果为 false,如果不相同则结果为 true,
!(非)运算符:就是逻辑非,取反,如:运算符后是 false,则结果为 true。
& 与 &&、| 与 || 的最终结果是一样的,但是他们之间还是有区别的:
&& 运算符:具有短路效果,如果运算符左边为 false,右边将不再执行直接给出结果为 false。
而 & 运算符:即使运算符左边已经为 false,还是会执行运算符右边,最后再结合起来判断得出最后结果为 false。
| 运算符与 || 运算符类似。
二、位运算符
位运算符有:&、|、^、~、<<、>>、<<<、>>>
注意:如果 &、|、^ 这三个运算符两边是数值则为位运算符,如果两边是 boolean 类型值则作为逻辑运算符。
位运算符:进行的操作都是二进制的,也就是说在操作之前需要先把数据转换为二进制数。
多态:
这里我一直没明白的点是,类似Shape circle = new Circle()的代码的为什么这么写?对比:Circle circle = new Circle();好在了哪里?为什么circle不能调用Circle特有的方法?向上转型意义所在。编译时是shape,但运行时对象的实际类型是 Circle。这句话什么意思?最后对应的内存图怎么画。堆里有没有父类shape?
Shape circle = new Circle()
面向对象编程中的多态性
在面向对象编程中,多态性允许使用父类或接口类型的引用来指向子类对象。这种设计方式使得代码更加灵活和可扩展。例如,Shape circle = new Circle()
中,Shape
是父类或接口,Circle
是子类。通过这种方式,可以在不改变代码结构的情况下,替换不同的子类对象。
提高代码的可维护性
使用父类或接口类型的引用可以减少代码的耦合度。如果直接使用 Circle circle = new Circle()
,代码会与具体的 Circle
类紧密耦合。而使用 Shape circle = new Circle()
,代码只依赖于 Shape
接口或父类,未来可以轻松替换为其他实现了 Shape
接口的类,如 Rectangle
或 Triangle
。
实现统一的接口调用
通过父类或接口类型的引用,可以统一调用接口中定义的方法。例如,Shape
接口可能定义了 draw()
方法,Circle
和 Rectangle
都实现了这个方法。使用 Shape circle = new Circle()
后,可以调用 circle.draw()
,而无需关心具体的子类实现
总结
Shape circle = new Circle()
这种写法充分利用了面向对象编程的多态性,提高了代码的灵活性和可维护性。通过使用父类或接口类型的引用,可以统一调用接口方法,并且在不改变代码结构的情况下,轻松替换不同的子类实现。
public class Test {public static void main(String args[]) {int x, y;x = 5 >> 2;y = x >>> 2;System.out.println(y);}
}
代码执行步骤
-
变量声明:
int x, y;
声明两个整数变量x
和y
。 -
计算
x = 5 >> 2
- 5 的二进制表示:
0000 0101
(假设为 32 位整数)。 - 右移 2 位(
>> 2
):将所有位向右移动 2 位,高位补符号位(正数补 0)。
结果:0000 0001
→ 十进制值为 1。 - 因此,
x
的值为 1。
- 5 的二进制表示:
-
计算
y = x >>> 2
- x 的值(1)的二进制:
0000 0001
。 - 无符号右移 2 位(
>>> 2
):将所有位向右移动 2 位,高位补 0(无论正负)。
结果:0000 0000
→ 十进制值为 0。 - 因此,
y
的值为 0。
- x 的值(1)的二进制:
-
输出结果:
System.out.println(y);
打印 0。
-
>>
与>>>
的区别:>>
(带符号右移):高位补符号位(正数补 0,负数补 1)。>>>
(无符号右移):高位始终补 0,适用于处理无符号数或需要逻辑右移的场景。
为什么有包装类
一、满足面向对象编程的需求
-
基本类型不是对象:
Java 是面向对象语言,但int
、double
等基本类型不具备对象的特性(如方法调用、继承)。包装类将基本类型转换为对象,使其可参与面向对象的操作。 -
泛型的限制:
泛型(如List<T>
、Map<K,V>
)只能使用对象类型,无法直接存储基本类型。包装类解决了这一问题:List<Integer> list = new ArrayList<>(); // 合法 // List<int> list = new ArrayList<>(); // 非法
二、支持序列化与反射
-
序列化(Serialization):
对象可通过序列化在网络传输或保存到文件,而基本类型不支持。包装类使基本数据具备序列化能力:Integer num = 10; // 可序列化 ObjectOutputStream oos = new ObjectOutputStream(...); oos.writeObject(num); // 合法
-
反射(Reflection):
反射机制只能操作对象,包装类允许基本类型参与反射:Class<?> clazz = Integer.class; Method method = clazz.getMethod("toString");
三、提供实用方法
包装类提供了许多静态方法和常量,增强基本类型的功能:
// 字符串转基本类型
int num = Integer.parseInt("123");// 进制转换
String binary = Integer.toBinaryString(255); // "11111111"// 最大值/最小值常量
long max = Long.MAX_VALUE; // 9223372036854775807// 自动装箱/拆箱
Integer obj = 10; // 自动装箱:int → Integer
int primitive = obj; // 自动拆箱:Integer → int
四、自动装箱与拆箱(Autoboxing/Unboxing)
Java 5 引入的特性,允许基本类型与包装类自动转换,简化代码:
// 自动装箱
Integer a = 10; // 等价于 Integer a = Integer.valueOf(10);// 自动拆箱
int b = a; // 等价于 int b = a.intValue();// 集合操作
List<Integer> list = new ArrayList<>();
list.add(1); // 自动装箱:int → Integer
int first = list.get(0); // 自动拆箱:Integer → int
final和finally的区别??
一、final(修饰符)
1. 作用
- 修饰类:类不可被继承(如
String
、Math
)。 - 修饰方法:方法不可被重写。
- 修饰变量:变量成为常量,只能赋值一次。
2. 示例
// 1. 修饰类
final class ImmutableClass { }
// class SubClass extends ImmutableClass {} // 编译错误:无法继承 final 类// 2. 修饰方法
class Parent {public final void print() { }
}
// class Child extends Parent {
// @Override
// public void print() {} // 编译错误:无法重写 final 方法
// }// 3. 修饰变量
final int MAX_SIZE = 100;
// MAX_SIZE = 200; // 编译错误:无法修改 final 变量
二、finally(异常处理)
1. 作用
在 try-catch
结构中,finally
块中的代码 无论是否发生异常都会执行,常用于资源释放(如关闭文件、网络连接等)。
2. 示例
try {FileInputStream file = new FileInputStream("test.txt");// 读取文件...
} catch (FileNotFoundException e) {e.printStackTrace();
} finally {// 无论是否发生异常,finally 块都会执行System.out.println("Finally block executed");