狂命爆肝21天,共51K字的JAVA学习笔记奉上,JAVA从入门到精通一文搞定,一文在手JAVA无忧
背景知识
Java 相关概念
- JavaSE (Java Standard Edition): 基础版,用于开发桌面应用程序。
- JavaEE (Java Enterprise Edition): 企业版,用于开发企业级应用程序。
- JavaME (Java Micro Edition): 微型版,用于开发嵌入式系统和移动设备应用程序。
编译与运行
-
编译阶段:
- 源文件: .java 文件。
- 字节码文件: .class 文件。
- 编译工具: javac.exe,用于将 .java 文件编译为 .class 文件。
- 命令: javac 文件名.java
- 编译包: javac -d 编译后存放路径 java源文件路径
-
运行阶段:
- 运行工具: java.exe,用于运行 .class 文件。
- 命令: java 类名(不带 .class 后缀)
- JVM (Java Virtual Machine): Java 虚拟机,负责执行字节码文件。
- 运行工具: java.exe,用于运行 .class 文件。
开发环境
- JDK (Java Development Kit): Java 开发工具包,包含编译器、调试器等开发工具。
- JRE (Java Runtime Environment): Java 运行环境,包含 JVM 和运行 Java 程序所需的库。
- JVM (Java Virtual Machine): Java 虚拟机,负责执行字节码文件。
工具与格式
- native2ascii: 用于将 Unicode 字符转换为 \u 表示的 ASCII 格式。
- UML (Unified Modeling Language): 面向对象设计图,用于表示类、接口、继承、实现等关系。
- 空心箭头: 指向父类(继承)。
- 空心虚线箭头: 指向接口(实现)。
- 实心实线箭头: 表示关联关系。
注释
- 单行注释: //
- 多行注释: /* */
- 文档注释: /** */,用于生成帮助文档。
类与方法结构
类体 { 方法体 { java语句; } }
总结
- JavaSE 是基础版,JavaEE 是企业版,JavaME 是微型版。
- 编译 使用 javac,运行 使用 java。
- JDK 是开发工具包,JRE 是运行环境,JVM 是虚拟机。
- UML 用于面向对象设计,注释 用于代码说明。
- 类与方法 的基本结构如上所示。
Java SE API 和文档
一、集成开发环境(IDEA)
以下是用户提供的快捷键和组织方式的总结:
组织方式
- Project(工程): 最高层级,包含多个模块。
- Module(模块): 工程下的子模块,包含多个包。
- Package(包): 模块下的子包,用于组织类和资源。
字体设置
- 路径: File -> Settings -> Font
用于调整编辑器的字体样式和大小。
快捷键分类总结
导航与操作
-
展开/移动列表:
- 左右箭头: 展开或折叠列表。
- 上下箭头: 在列表中移动。
-
切换与定位:
- Alt+左右箭头: 切换 Java 程序。
- Alt+上下箭头: 在方法间快速移动。
- Alt+标号: 打开标号窗口。
- Ctrl+G: 定位到文件的某一行。
- Ctrl+点击: 切换源码。
- Ctrl+H: 查看实现类。
-
查找与搜索:
- Ctrl+Shift+N: 查找文件。
- Ctrl+N: 查找类文件。
- Ctrl+F12: 在当前类中查找一个方法。
编辑与格式化
-
代码编辑:
- Ctrl+Y: 删除一行。
- Shift+F6: 重命名。
- Alt+拖动: 一次编辑多行。
- Ctrl+Alt+T: 将选中的代码放在 TRY{}、IF{}、ELSE{} 中。
-
代码提示与自动补全:
- Ctrl+空格: 代码提示。
- Ctrl+P: 方法参数提示。
- Ctrl+J: 自动代码。
- Ctrl+Alt+Space: 类名或接口名提示。
-
格式化与优化:
- Ctrl+Alt+L: 格式化代码。
- Ctrl+Alt+I: 自动缩进。
- Ctrl+Alt+O: 优化导入的类和包。
运行与纠错
-
运行程序:
- Ctrl+Shift+F10: 运行当前程序。
-
纠错与提示:
- Alt+回车: 纠错提示。
窗口操作
- 全屏模式:
- Ctrl+Shift+F12: 切换全屏模式。
总结
- 组织方式: 工程 -> 模块 -> 包,层级清晰,便于管理。
- 快捷键:
- 导航与查找:快速定位文件、类、方法。
- 编辑与格式化:提高代码编写效率。
- 运行与纠错:快速运行程序并修复错误。
- 窗口操作:优化开发环境布局。
二、JVM内存划分
局部变量在方法体中声明,运行阶段内存在栈中分配
方法区内存:字节码文件在加载 的时候将其放在方法区之中(最先有数据,调用方法时在栈内分配空间)
堆内存(heap):new对象(成员变量中的实例变量(一个对象一份)在java对象内部存储),只能通过引用调用操作
栈(stack)内存:栈帧永远指向栈顶元素,栈顶元素处于活跃状态,先进后出,后进先出(存储局部变量)
内存区域与数据存储
-
堆内存(Heap):
- 存储实例变量(对象属性)。
- 每个 JVM 实例只有一个堆内存,所有线程共享。
- 垃圾回收器(GC)主要针对堆内存进行回收。
-
方法区(Method Area):
- 存储静态变量(类变量)和类元数据(如类信息、常量池等)。
- 每个 JVM 实例只有一个方法区,所有线程共享。
- 方法区是最先有数据的内存区域,因为类加载时静态变量和类信息会初始化。
-
栈内存(Stack):
- 存储局部变量和方法调用栈帧。
- 每个线程有一个独立的栈内存,线程私有。
- 栈内存是使用最频繁的内存区域,因为方法调用和局部变量的生命周期较短。
变量存储位置
-
局部变量:
- 存储在栈内存中。
- 生命周期与方法调用一致,方法结束时局部变量会被销毁。
-
实例变量:
- 存储在堆内存中。
- 生命周期与对象一致,对象被垃圾回收时实例变量会被销毁。
-
静态变量:
- 存储在方法区中。
- 生命周期与类一致,类卸载时静态变量会被销毁。
垃圾回收器(GC)
-
主要目标:
- 垃圾回收器主要针对堆内存进行回收,清理不再使用的对象。
- 栈内存和方法区的垃圾回收机制与堆内存不同。
-
特点:
- 堆内存是垃圾回收的主要区域,因为对象生命周期较长且占用内存较大。
- 栈内存和方法区的垃圾回收效率较高,因为它们的生命周期较短且数据量相对较小。
三、关键字:
类与关键字
-
public:
- 表示公开的类,类名必须与文件名一致,且一个文件中只能有一个 public 类。
-
class:
- 用于定义一个类。
-
static:
- 表示静态的,修饰的成员变量或方法属于类级别,不依赖于对象。
- 静态变量在类加载时初始化,存储在方法区内存中。
- 静态方法不能访问实例变量或实例方法,需要通过对象访问。
-
break:
- 用于跳出循环或 switch 语句。
-
continue:
- 用于跳过当前循环的剩余部分,直接进入下一次循环。
- 语法:continue 循环名称; 或 循环名称:。
-
this:
- 表示当前对象的引用。
- 用于区分局部变量和实例变量,或在构造方法中调用其他构造方法(this(实参))。
- 不能用于静态方法中。
-
native:
- 用于调用 JVM 本地程序。
输入与输出
-
System.out.println():
- 控制台输出,println 表示输出并换行。
-
键盘输入:
- 创建键盘扫描器对象:java.util.Scanner s = new java.util.Scanner(System.in);
- 字符串输入:String user = s.next();
- 整数输入:int num = s.nextInt();
final 关键字
-
修饰类:
- 类不能被继承。
-
修饰方法:
- 方法不能被重写。
-
修饰变量:
- 变量不能被修改。
- 修饰的成员变量必须手动赋值。
- 修饰的引用一旦指向一个对象,就不能指向其他对象,但所指向的内存可以修改。
-
常量:
- 定义常量:public static final 类型 常量名 = 值;
- 命名规则:全部大写,用下划线分隔。
super 关键字
-
作用:
- 代表当前对象的父类型特征。
- 用于访问父类的属性、方法或调用父类的构造方法。
-
语法:
- 访问父类属性或方法:super.
- 调用父类构造方法:super()
-
规则:
- 不能用于静态方法中。
- 如果父类和子类有同名属性,访问父类属性时不能省略 super。
- 构造方法的第一行如果没有 this() 或 super(),默认会调用 super()。
static 关键字
-
静态变量:
- 属于类级别,不依赖于对象,类加载时初始化。
-
静态方法:
- 类级别的方法,不能访问实例变量或实例方法。
-
静态代码块:
- 在类加载时执行,只执行一次。
- 语法:static {}
-
实例代码块:
- 在构造方法执行之前执行,用于对象初始化。
包与导入
-
package:
- 用于管理类,命名规则:公司域名倒序.项目名.模块名.功能名。
- 语法:package 包名;
-
import:
- 用于导入包中的类。
- 语法:import 包名.类名; 或 import 包名.*;
- java.lang.* 是核心语言包,无需导入。
-
快捷键:
- Ctrl+Shift+O:自动导入。
访问控制权限修饰符
-
private:
- 私有访问权限,只能在本类中访问。
-
default:
- 默认访问权限,可以被本包中的其他类访问。
-
protected:
- 受保护的访问权限,可以被本包及不同包的子类访问。
-
public:
- 公共访问权限,可以在任何地方访问。
-
类的修饰符:
- 类只能使用 public 或默认修饰符(缺省),内部类除外。
总结
- 类与关键字:public、class、static、this、super 等关键字的作用与用法。
- 输入与输出:控制台输出与键盘输入的基本操作。
- final:用于修饰类、方法、变量,表示不可修改。
- static:修饰类级别的成员,与对象无关。
- 包与导入:package 和 import 的使用及命名规则。
- 访问控制权限:private、default、protected、public 的访问范围。
四、Java基础
以下是用户提供的内容的总结:
标识符
-
定义:
- 用户有权命名的单词,包括类名、方法名、常量名、变量名、接口名等。
-
命名规则:
- 类名、接口名: 首字母大写,后面每个单词首字母大写(大驼峰命名法)。
- 方法名、变量名: 首字母小写,后面每个单词首字母大写(小驼峰命名法)。
- 常量名: 全部大写,单词间用下划线分隔。
字面值
- 定义: 数据本身,如数字、字符串等,通常以紫色显示。
变量
-
局部变量:
- 定义在方法体内,没有默认值,必须手动初始化。
- 生命周期与方法调用一致。
-
成员变量:
- 定义在类体内,有默认值(数值类型为 0,布尔类型为 false,引用类型为 null)。
- 分为实例变量和静态变量。
-
实例变量:
- 不带 static 关键字,属于对象级别。
- 必须通过对象引用访问(引用.变量名)。
- 存储在堆内存中。
-
静态变量:
- 带 static 关键字,属于类级别。
- 在类加载时初始化,存储在方法区内存中。
- 通过类名访问(类名.变量名)。
引用
- 定义: 是一个变量,可以是实例变量或局部变量。
- 实例变量: 类名 引用 = new 类名();
- 局部变量: 引用 变量名 = new 引用();
数据类型
-
基本数据类型:
- 整数型: byte(1 字节)、short(2 字节)、int(4 字节)、long(8 字节,后缀 L)。
- 浮点型: float(4 字节)、double(8 字节)。
- 布尔型: boolean(1 字节)。
- 字符型: char(2 字节)。
-
引用数据类型:
- 字符串: String,不可变,存储在方法区字符串池中。
-
比较:
- 基本数据类型使用 == 判断相等。
- 引用数据类型(包括 String)使用 equals 判断相等。
字符编码
- 发展顺序: ASCII
位运算符
- 逻辑异或(^): 两边不一样为真。
- 短路与(&&): 左边为假时直接返回假。
- 按位与(&): 将操作数转换为二进制后按位与。
- 短路或(||): 左边为真时直接返回真。
- 左移(): 正数用 0 填充,负数用 1 填充。
- 无符号右移(>>>): 无论正负都用 0 填充。
- 按位取反(~): 将二进制每一位取反,结果为 -(n+1)。
方法(函数)
-
定义:
[修饰符列表] 返回值类型 方法名(形参列表) { 方法体; return; // return 后不能跟语句 }
-
调用: 类名.方法名(实参列表);
-
实例方法: 不带 static,需要对象参与。
-
静态方法: 带 static,与对象无关。
方法重载(Overload)
- 定义: 在同一类中,方法名相同但参数列表不同。
- 特点: 与返回值类型和修饰符列表无关。
方法递归
- 定义: 方法调用自身,每次递归都会分配新的内存空间(压栈)。
-
示例:
public static int sum(int n) { if (n == 1) { return 1; } return n + sum(n - 1); }
方法覆盖(Override)
- 定义: 发生在继承关系中,子类重写父类的方法。
- 规则:
- 方法名、返回值类型、形参列表必须与父类一致。
- 访问权限不能比父类更低,抛出异常不能更多。
- 限制:
- 私有方法、构造方法不能覆盖。
- 静态方法不存在覆盖。
总结
- 标识符: 命名规则与用途。
- 变量: 局部变量、实例变量、静态变量的定义与存储位置。
- 数据类型: 基本数据类型与引用数据类型的区别。
- 位运算符: 各种位运算符的作用与用法。
- 方法: 定义、调用、重载、递归与覆盖的规则与特点。
五、Java 控制流与 Lambda 表达式
1. 控制流语句
-
If-Else 语句:
if (条件) { // 语句 } else if (表达式) { // 语句 } else { // 语句 }
-
Switch 语句:
switch (关键词) { case 关键词: // java语句 break; default: // 默认语句 }
-
For 循环:
for (初始表达式; 布尔表达式; 更新循环体) { // 循环体 }
-
增强 For 循环(For Each):
for (元素类型 变量名 : 数组或集合) { System.out.println(变量名); }
-
While 循环:
while (表达式) { // 循环体 }
-
Do-While 循环:
do { // 循环体 } while (布尔表达式);
2. Java 标签
- 标签用于控制嵌套循环的跳转和中断。
- 语法:label:
- 用法:
- continue label;:跳过当前循环,继续执行标签处的循环。
- break label;:结束标签处的循环,执行循环后的代码。
3. Lambda 表达式
-
实现 Runnable:
// Java 8 之前 new Thread(new Runnable() { @Override public void run() { System.out.println("Before Java8, too much code for too little to do"); } }).start(); // Java 8 方式 new Thread(() -> System.out.println("In Java8, Lambda expression rocks !!")).start();
-
事件处理:
// Java 8 之前 JButton show = new JButton("Show"); show.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("Event handling without lambda expression is boring"); } }); // Java 8 方式 show.addActionListener((e) -> { System.out.println("Light, Camera, Action !! Lambda expressions Rocks"); });
-
列表迭代:
// Java 8 之前 List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API"); for (String feature : features) { System.out.println(feature); } // Java 8 之后 features.forEach(n -> System.out.println(n)); // 使用方法引用 features.forEach(System.out::println);
-
Map 和 Reduce:
// 不使用 lambda 表达式 List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500); for (Integer cost : costBeforeTax) { double price = cost + .12 * cost; System.out.println(price); } // 使用 lambda 表达式 costBeforeTax.stream().map((cost) -> cost + .12 * cost).forEach(System.out::println); // 使用 reduce 计算总和 double bill = costBeforeTax.stream().map((cost) -> cost + .12 * cost).reduce((sum, cost) -> sum + cost).get(); System.out.println("Total : " + bill);
-
对列表的每个元素应用函数:
List G7 = Arrays.asList("USA", "Japan", "France", "Germany", "Italy", "U.K.", "Canada"); String G7Countries = G7.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", ")); System.out.println(G7Countries);
-
计算集合元素的最大值、最小值、总和以及平均值:
List primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29); IntSummaryStatistics stats = primes.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("Highest prime number in List : " + stats.getMax()); System.out.println("Lowest prime number in List : " + stats.getMin()); System.out.println("Sum of all prime numbers : " + stats.getSum()); System.out.println("Average of all prime numbers : " + stats.getAverage());
总结
- 控制流语句:用于控制程序的执行流程,包括条件判断、循环等。
- Java 标签:用于控制嵌套循环的跳转和中断。
- Lambda 表达式:简化了匿名类的使用,使代码更简洁,特别是在实现函数式接口(如 Runnable、ActionListener)时非常有用。
- Stream API:提供了强大的集合操作功能,如 map、reduce、forEach 等,使得对集合的处理更加高效和简洁。
六、面向对象
面向过程与面向对象的对比
-
面向过程:
- 因果关系:关注问题的具体步骤和流程。
- 具体过程:强调如何一步步解决问题。
- 耦合度高:各个模块之间依赖性强,修改一个模块可能会影响其他模块。
- 软件拓展性差:由于耦合度高,系统的扩展和维护较为困难。
-
面向对象:
- 分类对象:将问题分解为多个对象,每个对象负责特定的功能。
- 关系层度低:对象之间的依赖关系较弱,耦合度低。
- 关注对象功能:关注对象能完成哪些功能,而不是具体的实现步骤。
- 三大特征:
- 封装性:将复杂的事务封装起来,只保留简单的操作入口。封装后形成独立的对象,提高了代码的复用性、适应性和安全性。
- 继承性:实现代码复用,最重要的是支持多态和方法覆盖。
- 多态性:父类型的引用可以指向子类型对象,降低程序耦合度,提高扩展力。
面向对象的分析与设计
- 面向对象的分析(OOA):分析问题域,识别对象及其关系。
- 面向对象的设计(OOD):设计对象的结构和行为,定义类及其关系。
- 面向对象的编程(OOP):使用编程语言实现设计,创建对象并实现其功能。
类与对象
- 类:高度抽象的对象的集合,是一个模板。
- 静态代码块:类加载时执行。
- 实例代码块:实例化时执行。
- 静态变量:类级别的变量。
- 实例变量:对象级别的变量,存储在堆内存中。
- 构造方法:创建对象时调用,用于初始化实例变量。
- 静态方法:类级别的方法。
- 实例方法:对象级别的方法。
- 成员变量:对象的属性,描述对象的状态。
- 成员方法:对象的行为,描述对象的动作。
- 对象:类的具体实例。
- 创建对象:类名 对象名称 = new 类名();
- 使用对象:对象名称.属性名 或 对象名称.方法名()
- 修改对象:引用.变量名 = 值
- 引用与对象:引用保存了对象的地址,指向堆内存中的对象。多个引用可以指向同一个对象,但一个引用只能指向一个对象。
User u=new User(); Address a=new Address(); u.addr=a; Print(u.addr.city); A.city=”天津”; Print(u.addr.city);
封装
- 私有化属性:使用private关键字将属性私有化。
- 提供操作入口:通过getter和setter方法提供对属性的访问和修改。
- 读取属性:public 数据类型 get属性名() { return 属性; }
- 修改属性:public void set属性名(数据类型 属性) { this.属性 = 属性; }
- 业务逻辑控制:在setter方法中添加业务逻辑进行安全控制。
构造方法
- 作用:创建对象并初始化实例变量。
- 语法:修饰符 构造方法名(形参) { 构造方法体; this.实例变量 = 形参; }
- 特点:没有返回值类型,方法名与类名一致,不能使用return返回值,但可以使用return结束方法。
- 调用:new 构造方法名(实参)
- 缺省构造器:如果没有定义构造方法,编译器会自动生成一个无参的缺省构造器。
继承
- 语法:[修饰符列表] class 子类名 extends 父类名 { 类体 = 属性 + 方法 }
- 单继承:Java中类只能继承一个父类。
- 继承关系:
- 父类:也称为基类、超类、superclass。
- 子类:也称为派生类、subclass。
- 不可继承:私有的属性和方法、构造方法。
- 间接继承:通过继承链,子类可以间接继承父类的父类。
- 默认继承:如果没有显式继承任何类,默认继承java.lang.Object类。
- super关键字:用于调用父类的属性、方法和构造方法。
多态
- 向上转型(Upcasting):子类转换为父类型,自动类型转换。
- 语法:父类 引用 = new 子类();
- 特点:编译通过,运行没有问题。
- 向下转型(Downcasting):父类转换为子类,强制类型转换。
- 语法:子类 引用 = (子类) 父类引用;
- 特点:存在隐患,可能导致ClassCastException异常。
- 动态绑定:父类型引用指向子类型对象,调用方法时实际执行的是子类的方法。
- instanceof运算符:用于在强制转换前检查对象的类型,避免ClassCastException异常。
- 语法:引用 instanceof 数据类型名
- 返回值:布尔类型,true表示引用指向的对象是后面的数据类型,false表示不是。
以下是关于 抽象类 和 接口 的总结:
抽象类
-
定义:
- 使用 abstract 关键字修饰的类,是类的进一步抽象。
- 属于引用数据类型。
-
语法:
[修饰符列表] abstract class 类名 {}
-
特点:
- 不能使用 private 或 final 修饰。
- 抽象类可以包含抽象方法和非抽象方法。
- 抽象类的子类可以是抽象类或非抽象类。
- 不能实例化(不能创建对象),但可以有构造方法,供子类使用。
-
抽象方法:
- 使用 abstract 关键字修饰,无方法体。
- 语法:[修饰符列表] abstract 返回值类型 方法名();
- 包含抽象方法的类一定是抽象类。
-
规则:
- 抽象类不一定有抽象方法,但抽象方法必须出现在抽象类中。
- 非抽象类继承抽象类时,必须实现所有抽象方法。
接口
-
定义:
- 使用 interface 关键字定义,是完全抽象的(特殊的抽象类)。
- 属于引用数据类型。
-
语法:
[修饰符列表] interface 接口名 {}
-
特点:
- 接口中只能包含常量和抽象方法(默认 public static final 和 public abstract,修饰符可省略)。
- 支持多继承,一个接口可以继承多个接口。
- 接口不能继承抽象类。
-
方法类型:
- 抽象方法: abstract 修饰(可省略)。
- 默认方法: default 修饰,提供默认实现。
- 静态方法: static 修饰,通过接口名调用。
-
实现:
- 类通过 implements 关键字实现接口。
- 非抽象类实现接口时,必须重写所有抽象方法。
- 一个类可以实现多个接口。
-
多态:
- 接口支持多态:父类型引用指向子类对象。
- 示例:接口名 引用 = new 实现类();
-
作用:
- 解耦合:调用者面向接口调用,实现者面向接口编写实现。
- 扩展性强:接口+多态可以降低程序耦合度。
抽象类与接口的区别
特性 抽象类 接口 抽象程度 半抽象(可以包含具体方法) 完全抽象(只能包含抽象方法) 构造方法 有构造方法,供子类使用 无构造方法 继承 单继承(一个类只能继承一个抽象类) 支持多继承(一个类可以实现多个接口) 内容 可以包含抽象方法和非抽象方法 只能包含常量和抽象方法 用途 抽象行为和数据 主要抽象行为 实例化 不能实例化 不能实例化 开发中的选择
-
抽象类:
- 当多个类有共同的属性和行为,且需要部分具体实现时使用。
- 适合定义“是什么”(is-a 关系)。
-
接口:
- 当需要定义一组行为规范,且不关心具体实现时使用。
- 适合定义“能做什么”(like-a 关系)。
示例
-
抽象类:
abstract class Animal { abstract void sound(); void sleep() { System.out.println("Sleeping..."); } }
-
接口:
interface Flyable { void fly(); }
-
实现与继承:
class Bird extends Animal implements Flyable { @Override void sound() { System.out.println("Chirp..."); } @Override public void fly() { System.out.println("Flying..."); } }
总结
-
面向对象编程通过封装、继承和多态三大特征,提高了代码的复用性、扩展性和维护性。
-
类与对象是面向对象编程的基础,类是对对象的抽象,对象是类的实例。
-
封装通过私有化属性和提供操作入口,增强了代码的安全性和可控性。
-
继承实现了代码的复用,并支持多态和方法覆盖。
-
多态通过向上转型和向下转型,降低了程序的耦合度,提高了扩展力。
-
面向抽象编程,而不是面向具体,可以进一步降低耦合度,提高系统的灵活性和可扩展性。
-
抽象类 用于定义类的共有特征,支持部分具体实现。
-
接口 用于定义行为规范,支持多继承和解耦合。
-
在实际开发中,根据需求选择抽象类或接口,合理使用可以提高代码的扩展性和可维护性。
七、类库
源码、字节码与帮助文档
-
源码:
- 理解程序:源码是程序员编写的原始代码,用于理解程序的逻辑和功能。
-
字节码:
- 程序开发使用:字节码是源码编译后的中间代码,由JVM执行。它是跨平台的,可以在任何支持JVM的系统上运行。
-
帮助文档:
- 对开发提供帮助:帮助文档是开发者的参考指南,通常通过javadoc生成。
- 注意使用版本同一:确保使用的帮助文档与代码版本一致,避免因版本差异导致的错误。
Object类(根类)
Object是Java中所有类的根类,提供了一些核心方法:
-
protected Object clone():
- 负责对象克隆,返回对象的副本。
-
boolean equals(Object obj):
- 判断两个对象是否相等。默认比较引用地址,通常需要重写以比较对象内容。
-
int hashCode():
- 返回对象的哈希代码值,用于哈希表等数据结构。
-
String toString():
- 返回对象的字符串表示形式。默认返回类名@哈希值,通常需要重写以提供更有意义的信息。
-
protected void finalize() throws Throwable:
- 垃圾回收器负责调用,用于对象销毁前的清理工作。
-
System.gc():
- 建议启动垃圾回收器,但不保证立即执行。
System类
System类提供了一些系统级别的操作:
-
System.gc():
- 建议启动垃圾回收器。
-
System.out:
- 静态变量,用于控制台输出。
-
System.out.print():
- 输出打印不换行。
-
System.out.println():
- 换行输出。
-
System.currentTimeMillis():
- 获取自1970年1月1日00:00:00到当前系统时间的总毫秒数。
-
System.exit(0):
- 退出JVM。
Arrays类
Arrays是数组工具类,提供了一些常用方法:
-
Arrays.sort(arr):
- 对数组进行排序。
-
Arrays.binarySearch(arr, key):
- 使用二分法查找元素,不存在时返回-1。
String类
String类用于操作字符串,提供了丰富的构造方法和方法:
-
构造方法:
- String(byte[] byte):将字节数组转换为字符串。
- String(char[] char):将字符数组转换为字符串。
- String(String string):复制字符串。
-
常用方法:
- char charAt(int index):返回指定索引的字符。
- int compareTo(String string):字典比较大小。
- boolean contains(String string):判断是否包含指定字符串。
- boolean endsWith(String string):判断是否以指定字符串结尾。
- boolean startsWith(String prefix):判断是否以指定前缀开头。
- boolean equals(Object anObject):比较字符串内容。
- boolean equalsIgnoreCase(String anotherString):忽略大小写比较。
- byte[] getBytes():将字符串转换为字节数组。
- int indexOf(String str):返回子字符串第一次出现的索引。
- int lastIndexOf(String str):返回子字符串最后一次出现的索引。
- boolean isEmpty():判断字符串是否为空。
- String replace(CharSequence target, CharSequence replacement):替换字符串。
- String substring(int beginIndex):截取字符串。
- char[] toCharArray():将字符串转换为字符数组。
- String toLowerCase():将字符串转换为小写。
- String toUpperCase():将字符串转换为大写。
- String[] split(String regex):按正则表达式拆分字符串。
- String trim():去除前后空白。
- static String valueOf():将其他类型转换为字符串。
StringBuffer与StringBuilder
-
StringBuffer:
- 线程安全,适用于多线程环境。
- 常用方法:append()、reverse()。
-
StringBuilder:
- 非线程安全,性能优于StringBuffer。
包装类
包装类用于将基本数据类型转换为对象:
- 常用包装类:
- Integer、Character等。
- 常用方法:
- int intValue():拆箱,将包装类转换为基本类型。
- static int parseInt(String s):将字符串转换为整数。
日期相关类
-
java.util.Date:
- 表示日期和时间。
-
SimpleDateFormat:
- 用于格式化日期。
- 常用方法:format()、parse()。
数字相关类
-
DecimalFormat:
- 用于格式化数字。
-
BigDecimal:
- 用于高精度计算,适用于财务数据。
-
Random:
- 用于生成随机数。
枚举(Enum)
枚举是一种特殊的类,用于定义一组常量:
enum Season { SPRING, SUMMER, AUTUMN, WINTER }
内部类
-
成员内部类:
- 定义在类中,可以访问外部类的所有成员。
-
局部内部类:
- 定义在方法中,只能在该方法内访问。
-
静态内部类:
- 使用static修饰,只能访问外部类的静态成员。
-
匿名内部类:
- 没有名称的内部类,通常用于实现接口或抽象类。
总结
- 源码是理解程序的基础,字节码是程序运行的关键,帮助文档是开发的指南。
- Object是Java的根类,提供了对象的基本操作。
- System类提供了系统级别的操作,如垃圾回收、时间获取等。
- String类用于操作字符串,提供了丰富的构造方法和方法。
- StringBuffer和StringBuilder用于字符串的拼接和修改,前者线程安全,后者性能更优。
- 包装类用于将基本数据类型转换为对象。
- 日期相关类用于处理日期和时间。
- 内部类提供了更灵活的代码组织方式。
八、数组
一维数组
-
定义:
- 数组是引用数据类型,存储在堆内存中。
- 可以存储各种数据类型,但不能直接存储对象,存储的是对象的引用(内存地址)。
-
特点:
- 数组元素类型统一,最后一个下标为 length - 1。
- 带有 length 属性,用于获取数组长度。
-
优点:
- 查询、查找、检索某个下标元素效率极高(内存连续,类型相同)。
-
缺点:
- 随机增删元素效率较低。
- 不能存储大数据量。
-
定义与初始化:
-
静态初始化:
数据类型[] 数组名 = {元素1, 元素2, ...};
-
动态初始化:
数据类型[] 数组名 = new 数据类型[长度];
-
赋值:
数组名[下标] = 值;
-
遍历:
-
使用 for 循环或增强 for 循环:
for (int i = 0; i
-
方法参数:
-
数组可以作为方法的参数:
void 方法名(数据类型[] 数组名) {}
-
main 方法的数组参数:
-
main 方法的参数是一个字符串数组,用于接收命令行参数:
public static void main(String[] args) {}
-
存储对象:
-
数组可以存储对象的引用:
类名[] 数组名 = new 类名[长度]; 数组名[0] = new 类名();
-
数组扩容:
-
新建一个大数组,然后将原数组拷贝过去:
int[] newArray = new int[原数组.length * 2]; System.arraycopy(原数组, 0, newArray, 0, 原数组.length);
-
数组拷贝:
-
使用 System.arraycopy 方法:
System.arraycopy(原数组, 原起点, 目标数组, 目标下标, 长度);
-
-
-
-
-
-
-
二维数组
-
定义:
- 二维数组是数组的数组,可以看作是一个表格。
-
语法:
数据类型[][] 数组名 = new 数据类型[行数][列数];
-
初始化:
-
静态初始化:
数据类型[][] 数组名 = {{元素1, 元素2}, {元素3, 元素4}};
-
动态初始化:
数据类型[][] 数组名 = new 数据类型[行数][列数];
-
遍历:
-
使用嵌套 for 循环:
for (int i = 0; i
-
-
总结
-
一维数组:
- 适用于存储一组相同类型的数据。
- 查询效率高,增删效率低。
- 可以通过 length 属性获取长度。
- 支持静态初始化和动态初始化。
-
二维数组:
- 适用于存储表格型数据。
- 可以看作是一维数组的数组。
- 支持静态初始化和动态初始化。
-
数组的优缺点:
- 优点:查询效率高,内存连续。
- 缺点:增删效率低,不能存储大数据量。
-
数组的应用场景:
- 存储一组固定长度的数据。
- 存储对象引用。
- 存储表格型数据(二维数组)。
示例
-
一维数组:
int[] arr = {1, 2, 3, 4, 5}; for (int i = 0; i
-
二维数组:
int[][] arr = {{1, 2}, {3, 4}}; for (int i = 0; i
-
数组存储对象:
Animal[] animals = new Animal[2]; animals[0] = new Cat(); animals[1] = new Dog();
-
数组扩容:
int[] src = {1, 2, 3}; int[] dest = new int[src.length * 2]; System.arraycopy(src, 0, dest, 0, src.length);
通过合理使用数组,可以高效地存储和操作数据,但需要注意其增删效率较低的缺点。
九、算法
以下是常见 排序算法 和 查找算法 的思想总结,并附带 Java 实例:
排序算法
-
冒泡排序(Bubble Sort):
-
思想:重复遍历数组,每次比较相邻元素,如果顺序错误则交换,直到没有需要交换的元素。
-
时间复杂度:O(n²)。
-
Java 实现:
public static void bubbleSort(int[] arr) { for (int i = 0; i arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } }
-
选择排序(Selection Sort):
-
思想:每次从未排序部分选择最小元素,放到已排序部分的末尾。
-
时间复杂度:O(n²)。
-
Java 实现:
public static void selectionSort(int[] arr) { for (int i = 0; i
-
插入排序(Insertion Sort):
-
思想:将未排序部分的元素逐个插入到已排序部分的正确位置。
-
时间复杂度:O(n²)。
-
Java 实现:
public static void insertionSort(int[] arr) { for (int i = 1; i = 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } }
-
快速排序(Quick Sort):
-
思想:选择一个基准元素,将数组分为两部分,左边小于基准,右边大于基准,递归排序。
-
时间复杂度:O(n log n)。
-
Java 实现:
public static void quickSort(int[] arr, int low, int high) { if (low
-
归并排序(Merge Sort):
-
思想:将数组分成两半,分别排序,然后合并。
-
时间复杂度:O(n log n)。
-
Java 实现:
public static void mergeSort(int[] arr, int left, int right) { if (left
7. 泛型的限制
- 不能使用基本类型:泛型类型必须是引用类型(如 Integer 而不是 int)。
- 不能创建泛型数组:例如 new T[10] 是非法的。
- 不能实例化泛型类型:例如 new T() 是非法的。
8. 泛型的应用场景
- 集合框架:如 List、Map 等。
- 工具类:如 Comparator、Comparable 等。
- 自定义数据结构:如栈、队列、链表等。
总结与拓展
- 泛型的作用:统一集合中元素的类型,提高代码的安全性和复用性。
- 自动推断机制:JDK 7 引入的钻石表达式简化了泛型代码。
- 自定义泛型:通过泛型类和泛型方法实现通用代码。
- 通配符:、 clazz = String.class;
-
Class.forName("包名.类名"):
-
加载类并默认进行静态初始化。
-
返回该类的 Class 对象。
-
示例:
Class clazz = Class.forName("java.lang.String");
-
Class.forName("包名.类名", false, 类加载器):
-
第二个参数为 false 时,不进行初始化;为 true 时,进行初始化。
-
示例:
Class clazz = Class.forName("java.lang.String", false, ClassLoader.getSystemClassLoader());
-
实例对象.getClass():
-
对类进行静态初始化和非静态初始化。
-
返回运行时实际对象所属类的 Class 对象。
-
示例:
String str = "Hello"; Class clazz = str.getClass();
-
-
-
-
-
-
-
-
3. Class 对象的特性
- 父子类 Class 对象不一致:
- 如果 A 是 B 的子类,则 A.class 和 B.class 返回的 Class 对象不同。
- 如果 a 是 A 的实例,则 A.class 和 a.getClass() 返回的 Class 对象一致。
4. Class 类的常用方法
- getName():返回类的全限定名(包名 + 类名)。
- getSuperclass():返回类的直接父类的 Class 对象。
- getInterfaces():返回类实现的所有接口的 Class 数组。
- isArray():判断该类是否是数组类型。
- isEnum():判断该类是否是枚举类型。
- isInterface():判断该类是否是接口。
- isPrimitive():判断该类是否是基本类型(如 int、boolean 等)。
- isAssignableFrom(Class cls):判断该类是否是 cls 的父类或父接口。
- getComponentType():如果该类是数组类型,返回数组的组件类型。
- asSubclass(Class clazz):将当前 Class 对象转换为 clazz 的子类类型。
5. asSubclass 方法的使用
-
作用:将当前 Class 对象转换为指定类的子类类型。
-
示例:
List strList = new ArrayList(); Class
-
-
-
-
- 向上转型(Upcasting):子类转换为父类型,自动类型转换。
- 类:高度抽象的对象的集合,是一个模板。
-
-
-
-
- 定义: 方法调用自身,每次递归都会分配新的内存空间(压栈)。
-
-
-
-
-