G:\Java\1.JavaSE
1.Java入门
2.变量_类型转换_运算符
3.流程控制
4.数组
5.方法
6.面向对象
7.异常
8.常用API
9.多线程
10.集合
11.IO流
12.网络编程
13.正则表达式
14.设计模式
15.JDK新特性
16.反射_注解
1.Java入门
1.1 JavaSE核心体系介绍
第一部分:计算机编程核心语法 - 数据类型、运算符、流程控制、数组、方法
第二部分:面向对象核心逻辑 - 类和对象、封装、继承、多态、抽象、接口
第三部分:JavaSE核心高级应用 - API、集合、IO流、多线程、网络编程、反射
第四部分:Java新特性 - Lambda表达式、函数式接口、新日期类、JDK8-17新特性
1.2 计算机语言发展说明
第一代:机器语言
第二代:汇编语言
第三代:高级语言(c,C++,Java,Python,Go)
1.3 Java生态圈介绍
Java 是目前应用最为广泛的开发平台之一。
作为一个平台,Java虚拟机的作用非常重要,任何一种能够编译成字节码的计算机语言都属于Java这个平台。Groovy、Scala、JRuby、Kotlin等都是Java平台的一部分,他们依赖于虚拟机,由JVM虚拟机实现跨平台。
1.4 Java语言介绍
Java21加入了纤程(虚拟线程)的概念,其核心就是轻量级的线程操作,提供更高的并发性和更低的资源消耗。
1. 纤程的概念
- 轻量级:纤程比传统线程更轻量,创建和上下文切换的开销更小。大量的虚拟线程可以在同一时间内运行。
- 高并发:通过使用虚拟线程,可以轻松处理大量并发请求,例如在服务器应用程序中。
- 简化编程模型:使用虚拟线程可以让异步编程变得更加简单,减少回调地狱的复杂性。
2. 纤程的示例
以下是一个简单的示例,展示如何在 Java 21 中使用虚拟线程来处理并发任务。
import java.util.concurrent.Executors; public class VirtualThreadExample { public static void main(String[] args) { // 创建一个虚拟线程工厂 var executor = Executors.newVirtualThreadPerTaskExecutor(); // 提交多个虚拟线程任务 for (int i = 0; i < 100; i++) { final int taskId = i; executor.submit(() -> { try { // 模拟任务处理 Thread.sleep(1000); System.out.println("Task " + taskId + " completed."); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } // 关闭执行器 executor.shutdown(); } }
3. 代码解析
- 创建虚拟线程执行器:使用
Executors.newVirtualThreadPerTaskExecutor()
创建一个虚拟线程执行器,每个任务都在一个新的虚拟线程中执行。- 提交任务:通过循环提交多个任务,每个任务模拟一个耗时的操作(如
Thread.sleep()
)。- 输出:任务完成时,打印任务 ID。
4. 纤程的优势
- 高并发处理:在实际应用中,可以轻松处理数千或数万个并发请求,而不会造成过大的资源消耗。
- 简化代码:使用虚拟线程,开发者可以使用同步编程模型,而无需使用复杂的异步调用和回调。
- 资源效率:由于虚拟线程的轻量级特性,可以在较少的内存和 CPU 资源下运行更多的并发任务。
总结
Java 21 的虚拟线程(纤程)概念使得高并发编程变得更简单、更高效。通过轻量级的解决方案,开发者可以更有效地利用系统资源,编写更易于理解和维护的代码。
1.5 Java软件开发
软件开发是根据用户要求建造出软件系统或者系统中的软件部分的过程。
软件开发是一项包括需求捕捉、需求分析、设计、实现和测试的系统工程。
软件一般是用某种程序设计语言来实现的。
字节:计算机中存储数据的最小计算单位,用byte或者B表示。
计算机中最小的存储单元是二进制位,用bit表示,1 byte = 8 bit。
1.5.1 JDK和JRE
1. JDK:Java Development Kit Java开发工具包
javac 编译工具
java 运行工具
jdb 调试工具
jhat 内存分析工具
2. JRE:Java Runtime Environment Java运行时环境
包含JVM和核心类库。
从JDK9开始jdk目录中没有单独的jre目录,因为jre作为一个运行时,里面不需要包含太多东西浪费空间,降低运行效率,在jdk9的时候引用模块化的技术,让开发者能按照自己的应用创建一个最小的运行时(比如一个微服务的部署应用仅仅需要非常小的runtime,而不是像以前一样不管应用复杂还是简单,都需要一个近百兆的jre运行),这样就提高了运行效率。
1.5.2 Java入门程序
开发程序3步骤:
编写代码 -> 编译 -> 运行
1.5.2 文档注释
Java 的文档注释(Javadoc)是一种特殊的注释格式,主要用于生成 API 文档。以下是文档注释的主要用途和优点:
1. 生成 API 文档
- 自动化文档生成:使用 Javadoc 工具,可以从代码中的文档注释生成 HTML 格式的 API 文档,方便开发者和用户查看。
- 标准化格式:通过规范化的注释格式,确保文档的一致性和可读性。
2. 提高代码可读性
- 注释类和方法:文档注释可以描述类、方法和字段的功能,使代码更易于理解。
- 解释使用方法:提供方法的参数、返回值和异常信息的详细说明,帮助其他开发者快速了解如何使用这些方法。
3. 支持团队协作
- 团队开发:在团队中,良好的文档注释可以帮助新成员了解项目的结构和功能,减少沟通成本。
- 维护和更新:文档注释可以帮助开发者在维护和更新代码时,快速理解旧代码的意图和设计。
4. 合同式编程
- 明确接口:通过文档注释,可以明确类和方法的行为规范,类似于软件的“合同”,确保实现符合预期。
- 提供示例:可以在文档中包含使用示例,帮助用户理解如何正确使用 API。
5. 集成开发环境(IDE)支持
- 代码提示:许多 IDE(如 IntelliJ IDEA 和 Eclipse)会根据文档注释提供代码提示和文档查看功能,增加开发效率。
- 自动生成文档:在 IDE 中,可以方便地生成和更新 Javadoc 文档。
示例:以下是一个简单的 Java 类及其文档注释的示例:
/** * 这是一个示例类,用于演示文档注释的用法。 */ public class Example { /** * 计算两个整数的和。 * * @param a 第一个整数 * @param b 第二个整数 * @return 两个整数的和 */ public int add(int a, int b) { return a + b; } }
javadoc 完整命令
使用 Javadoc 工具可以生成 Java 代码的 API 文档。以下是 Javadoc 的完整命令及其示例。
Javadoc 命令格式
javadoc [options] [packagenames] [sourcefiles] [@files]
常用选项
-d <directory>
:指定输出目录。-sourcepath <path>
:指定源文件的路径。-subpackages <package>
:包含子包的文档。-author
:包括类的作者信息。-version
:包括版本信息。-private
:包括私有成员的文档。示例命令
假设你有以下 Java 文件结构:
src/ ├── com/ │ └── example/ │ ├── Example.java │ └── Utils.java
1. 生成基本 API 文档
javadoc -d doc -sourcepath src -subpackages com -author -version
- 解释:
-d doc
:指定输出目录为doc
。-sourcepath src
:指定源代码路径为src
。-subpackages com
:文档中包含com
包及其子包的内容。-author
:在文档中包含作者信息。-version
:在文档中包含版本信息。2. 生成特定文件的 API 文档
如果只想生成
Example.java
的文档,可以指定文件名:javadoc -d doc -sourcepath src src/com/example/Example.java
3. 使用 @files 选项
如果你有一个文件列表,可以将它们放在一个文本文件中。例如,创建一个名为
filelist.txt
的文件,内容如下:src/com/example/Example.java src/com/example/Utils.java
然后使用以下命令:
javadoc -d doc -sourcepath src @filelist.txt
4. 生成 HTML 文档并在浏览器中查看
运行命令后,可以通过浏览器打开
doc/index.html
查看生成的文档。总结
通过 Javadoc,可以轻松生成 Java 代码的 API 文档。使用不同的选项和参数,可以根据需要定制生成的文档内容和格式。
javadoc -d api -author -version Demo.java
改变输入法设置,防止来回切换输入法.
1.5.3 关键字
关键字:Java提前定义好的,具有特殊含义的小写单词.
Java 语言中有一组预定义的关键字,具有特殊的含义。这些关键字是小写的,不能用作变量名、方法名或类名。以下是 Java 的所有关键字:
Java 关键字列表
控制流关键字
break
case
catch
class
default
do
else
enum
extends
finally
for
if
implements
import
instanceof
interface
native
new
package
private
protected
public
return
switch
synchronized
this
throw
throws
try
while
数据类型关键字
boolean
byte
char
double
float
int
long
short
void
修饰符关键字
abstract
assert
const
(未使用)goto
(未使用)final
finally
static
strictfp
transient
volatile
其他关键字
null
true
false
总结
Java 中的关键字总共包括 50 个。这些关键字在 Java 语言中具有特殊的语法意义,是编写 Java 程序时必须遵循的重要部分。
1.5.4 字符编码问题
编码:保存数据的过程是编码的过程;
解码:读取数据的过程是解码过程.
注意:
编码和解码遵守的编码规则要一样.
常见的编码规范:GBK,UTF-8
GBK:专门为中文所设计的编码.
ANSI:代表的是GBK,一个中文字符在GBK中占2个字节.
UTF-8:一个中文字符在UTF-8中占3个字节.
1.5.5 常见问题
1.Java文件名必须和类名是一致的吗?
在 Java 中,文件名必须与公共类的类名一致。这是 Java 语言的一个重要规范,确保了代码的可读性和组织性。以下是详细说明:
1. 公共类(public class)
- 一致性要求:如果一个类被声明为
public
,那么它所在的文件名必须与该类名完全一致,包括大小写。例如,如果有一个公共类MyClass
,那么文件名必须是MyClass.java
。2. 非公共类
- 没有一致性要求:对于非公共类(即没有
public
修饰符的类),文件名可以与类名不同。例如:class MyClass { // ... }
在这种情况下,文件名可以是
AnythingElse.java
。3. 多个类
- 一个文件只能有一个公共类:一个 Java 源文件可以包含多个类,但只能有一个类是
public
,且该公共类的名称必须与文件名相同。如:public class MyClass { // ... } class AnotherClass { // ... }
在这个例子中,文件名必须是
MyClass.java
。总结
- 公共类:文件名必须与公共类名一致。
- 非公共类:文件名可以与非公共类名不同。
- 只能有一个公共类:一个文件只能有一个公共类,且该公共类的名称必须与文件名相同。
2.内部类必须是静态的吗,为什么?
内部类在 Java 中不一定必须是静态的。Java 提供了两种类型的内部类:非静态内部类和静态内部类。下面是对这两种类型的详细说明及其区别:
1. 非静态内部类
- 定义:非静态内部类(Inner Class)是定义在另一个类内部的类,没有
static
修饰符。- 特点:
- 可以直接访问外部类的实例变量和方法,包括私有变量和方法。
- 每个非静态内部类的实例都与外部类的实例关联。
示例
public class OuterClass { private String outerField = "Outer Field"; class InnerClass { public void display() { System.out.println("Accessing: " + outerField); } } }
2. 静态内部类
- 定义:静态内部类(Static Nested Class)是定义在另一个类内部并带有
static
修饰符的类。- 特点:
- 不能直接访问外部类的实例变量和方法,只能访问外部类的静态成员(变量和方法)。
- 静态内部类的实例不依赖于外部类的实例。
示例
public class OuterClass { private static String staticOuterField = "Static Outer Field"; static class StaticInnerClass { public void display() { System.out.println("Accessing: " + staticOuterField); } } }
3. 总结
- 非静态内部类:可以访问外部类的实例成员,实例依赖于外部类的实例。
- 静态内部类:不能访问外部类的实例成员,只能访问静态成员,实例不依赖于外部类的实例。
结论
内部类不一定必须是静态的。选择使用非静态内部类或静态内部类取决于你的具体需求和上下文。如果需要访问外部类的实例成员,使用非静态内部类;如果只需要访问静态成员,可以使用静态内部类。
示例代码
public class OuterClass { private String outerField = "Outer Field"; // 外部类的实例变量 // 非静态内部类 class InnerClass { public void display() { // 访问外部类的实例变量 System.out.println("Accessing: " + outerField); } } } class Main { public static void main(String[] args) { // 第一步:创建外部类的实例 OuterClass outer = new OuterClass(); // 第二步:使用外部类的实例创建非静态内部类的实例 OuterClass.InnerClass inner = outer.new InnerClass(); // 调用非静态内部类的方法 inner.display(); // 输出: Accessing: Outer Field } }
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
3. 非静态内部类在实际开发中有哪些常见的应用场景?
非静态内部类在 Java 开发中有多种常见的应用场景,以下是一些典型的使用场景:
1. 逻辑分组
非静态内部类可以将相关的功能和数据组织在一起,增强代码的可读性和逻辑性。例如,如果某个类的功能依赖于外部类的状态,可以将其定义为非静态内部类。
public class OuterClass { private String outerField = "Outer Field"; class InnerClass { public void display() { System.out.println("Accessing: " + outerField); } } }
2. 实现回调机制
在处理事件或回调时,非静态内部类可以方便地访问外部类的实例变量或方法,适合用于 GUI 事件处理等场景。
public class Button { private String label; public Button(String label) { this.label = label; } public void setOnClickListener(ClickListener listener) { listener.onClick(); } public class ClickListener { public void onClick() { System.out.println(label + " clicked!"); } } }
Button enterButton = new Button("Enter"); Button.ClickListener clickListener = enterButton.new ClickListener(); enterButton.setOnClickListener(clickListener);
3. 访问外部类的私有成员
非静态内部类可以直接访问外部类的私有成员,适合需要封装和保护数据的场景。
public class OuterClass { private int secret = 42; class InnerClass { public void revealSecret() { System.out.println("The secret is: " + secret); } } }
4. 数据结构
非静态内部类可以用于构建数据结构,例如链表或树的节点类,方便访问外部类的状态。
public class LinkedList { private Node head; class Node { int data; Node next; Node(int data) { this.data = data; } } }
5. 状态管理
在某些情况下,非静态内部类可以用来维护和管理外部类的状态,帮助实现更复杂的逻辑。
public class Order { private String orderId; public Order(String orderId) { this.orderId = orderId; } class OrderDetail { private String product; public void printOrder() { System.out.println("Order ID: " + orderId + ", Product: " + product); } } }
总结
非静态内部类在实际开发中非常有用,尤其是在需要访问外部类实例的状态、逻辑分组相关功能、实现回调机制、构建数据结构等场景中。通过合理使用非静态内部类,可以增强代码的可读性和组织性。
4.静态内部类的性能优势是什么?
静态内部类在 Java 中有几个性能优势,主要体现在以下几个方面:
1. 无需持有外部类的引用
- 内存效率:静态内部类不需要持有外部类的引用,这意味着在创建静态内部类的实例时,不会创建外部类的实例。这可以节省内存,尤其是在外部类的实例可能非常重或者不需要时。
2. 更快的实例创建
- 实例化速度:因为静态内部类不依赖于外部类的实例,可以在没有外部类实例的情况下直接创建其实例。这样可以减少对象创建的开销,特别是在需要频繁创建内部类实例时。
3. 适合多线程环境
- 线程安全:静态内部类可以独立于外部类进行实例化,适合在多线程环境中使用。因为它不持有外部类的状态,减少了对外部类实例的同步需求,有助于降低并发问题。
4. 逻辑清晰
- 代码组织:静态内部类可以清晰地组织相关功能,使代码更加模块化。这种结构可以提高代码的可读性,便于维护和测试。
5. 不影响外部类的状态
- 独立性:静态内部类的实例不依赖于外部类的状态,因此可以在不影响外部类的情况下进行操作。这种独立性可以减少潜在的错误和复杂性。
总结
静态内部类的性能优势主要体现在内存使用、实例化速度、线程安全、代码组织和对外部类状态的独立性上。在需要高效且清晰的设计时,使用静态内部类是一个合理的选择。
5.如何在静态内部类中使用外部类的实例?
在 Java 中,静态内部类无法直接访问外部类的实例变量和方法,因为它不持有外部类的实例引用。不过,可以通过创建外部类的实例来访问其成员。以下是几种常见的方法来在静态内部类中使用外部类的实例:
1. 通过外部类的实例
你可以在静态内部类中创建外部类的实例,从而访问外部类的实例变量和方法。
public class OuterClass { private String outerField = "Outer Field"; static class StaticInnerClass { public void display() { // 创建外部类的实例 OuterClass outer = new OuterClass(); System.out.println("Accessing: " + outer.outerField); } } }
2. 通过构造函数传递外部类的实例
在静态内部类的构造函数中,可以传入外部类的实例,从而在内部类的方法中使用这个实例。
public class OuterClass { private String outerField = "Outer Field"; static class StaticInnerClass { private OuterClass outer; // 构造函数接受外部类的实例 public StaticInnerClass(OuterClass outer) { this.outer = outer; } public void display() { System.out.println("Accessing: " + outer.outerField); } } } // 使用示例 public class Main { public static void main(String[] args) { OuterClass outer = new OuterClass(); OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass(outer); inner.display(); // 输出: Accessing: Outer Field } }
3. 使用外部类的静态方法
如果外部类有静态方法,可以直接调用这些静态方法,而不需要实例化外部类。
public class OuterClass { private static String outerStaticField = "Static Outer Field"; static class StaticInnerClass { public void display() { System.out.println("Accessing: " + OuterClass.outerStaticField); } } }
总结
虽然静态内部类无法直接访问外部类的实例成员,但可以通过创建外部类的实例或通过构造函数传递外部类实例来实现这一点。此外,静态方法和静态成员可以直接访问。通过这些方式,可以在静态内部类中灵活地使用外部类的功能。
6.非静态内部类与静态内部类有什么主要区别?
非静态内部类和静态内部类在 Java 中有几个主要区别,以下是它们的关键差异:
1. 访问外部类的成员
非静态内部类:
- 可以直接访问外部类的所有成员,包括实例变量和方法(包括私有成员)。
- 每个非静态内部类的实例都与外部类的某个实例关联。
静态内部类:
- 只能访问外部类的静态成员,无法直接访问外部类的实例成员。
- 不需要外部类的实例,因此静态内部类的实例与外部类的实例无关。
2. 实例化
非静态内部类:
- 必须先创建外部类的实例,然后才能创建非静态内部类的实例。
OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.new InnerClass();
静态内部类:
- 可以直接通过外部类的类名创建实例,不需要外部类的实例。
OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass();
3. 内存使用
非静态内部类:
- 每个非静态内部类的实例会持有一个指向外部类实例的引用,这可能会导致内存使用增加。
静态内部类:
- 不持有外部类实例的引用,内存使用更高效,特别是在不需要外部类实例的情况下。
4. 适用场景
非静态内部类:
- 适用于需要访问外部类实例状态的场景,例如实现回调或逻辑分组。
静态内部类:
- 适用于不需要访问外部类实例状态的场景,例如组织工具类或实现某些数据结构。
5. 代码设计
非静态内部类:
- 设计上通常用于与外部类紧密相关的功能。
静态内部类:
- 更加独立,适合用于与外部类的逻辑关系较弱的场景。
总结
非静态内部类和静态内部类在访问权限、实例化方式、内存使用、适用场景和代码设计上存在显著差异。选择哪种内部类取决于具体的需求和设计目标。
7.在多线程环境中,非静态内部类的使用有什么注意事项?
在多线程环境中使用非静态内部类时,有一些重要的注意事项需要考虑,以确保线程安全和资源管理。以下是一些关键点:
1. 外部类实例的引用
- 持有外部类实例的引用:非静态内部类会隐式持有外部类的实例引用。如果外部类的实例在不同线程中被共享,可能会导致线程安全问题。
2. 线程安全
同步:如果非静态内部类的实例方法访问或修改外部类的共享状态,必须考虑同步机制,确保线程安全。
public class OuterClass { private int sharedResource; class InnerClass { public synchronized void updateResource() { sharedResource++; } } }
3. 内存泄漏
- 避免内存泄漏ÿ