面向对象的语言:
- 封装:封装是将对象的属性和行为封装起来,不需要让外界知道具体实现细节;
- 继承:继承是可以在无需重新编写原有类的情况下,对原有类的功能进行扩展;
- 多态:多态指的是在一个类中定义的属性和功能被其他类继承后,当把子类对象直接赋值给父类引用变量时,相同引用类型的变量调用同一个方法所呈现出的多种不同行为特性。
技术平台:Java EE、Java SE、Java ME
Java组成:JDK > JRE > JVM
-
JDK = JRE + 开发工具集(javac 编译器、javadoc、jdb 调试器等);开发工具包(用于开发)
-
JRE = JVM + Java标准类库;运行时环境(用于运行)
-
JVM = 虚拟机(实际执行代码)
Java执行过程:编写代码、编译、加载、验证、执行
javac命令把.java源文件编译成.class字节码文件,然后用java命令启动 JVM(Java虚拟机),JVM 通过类加载器加载.class文件,再由解释器或 JIT 编译器将字节码转为机器码执行。
数据类型:基本数据类型、引用数据类型(类/接口/数组/枚举)
JVM(Java Virtual Machine)、JDK(Java Development Kit)、JRE(Java Runtime Environment)
命名规范
-
类:单词首字母大写。
-
变量/方法:从第二个单词起大写。
-
包:全小写。
-
类中方法外定义的变量称为字段(Field)
构造方法
-
方法名和类名相同
-
方法名没有返回值类型的声明
-
方法中不能用
return 返回值,但可单独写return语句来作为方法的结束。 -
没有自定义构造方法时,JVM提供一个默认的无参构造方法
JAVA有GC就没有
destruction,一次性完成类的初始化,避免代码冗余及遗漏。只有可实例化的对象类才有构造函数,抽象类和接口是没有的
Class(参数列表){//方法名和类名相同 this.属性=参数;}//无返回值
Class name=new Class(参数列表);关键字
>static<
| 维度 | static (静态/类成员) | 非static (实例成员) |
|---|---|---|
| 1. 归属主体 | 属于类本身 | 属于类的实例对象 |
| 2. 内存分配 | 类加载时分配在方法区 | 对象创建时分配在堆内存 |
| 3. 内存共享 | 所有对象共享同一份内存 | 每个对象独立内存 |
| 4. 生命周期 | 类加载 → 程序结束 | 对象创建 → 对象GC回收 |
| 5. 调用方式 | 类名.成员名 | 对象.成员名 |
| 6. this/super(方法/代码块) | 不能使用 | 可以使用 |
| 7. 访问限制(方法/代码块) | 只能访问静态成员 | 可访问静态+实例成员 |
| 8. 多态性 | 没有多态(只能隐藏) | 支持多态(可重写) |
| 9. 同步锁 | 使用类锁 (Class对象) | 使用对象锁 (this) |
| 10. 初始化时机 | 类加载时(静态块/声明时) | 对象创建时(构造块/声明时) |
| 11. 典型应用 | 工具方法、常量、单例、计数器 | 对象属性、业务方法、状态操作 |
执行顺序
- 父类静态 → 2. 子类静态 → 3. 父类(代码块/变量) → 4. 父类构造 → 5. 子类(代码块/变量) → 6. 子类构造
(静态变量、静态代码块谁先执行,取决于代码的书写顺序)
>Final<
- 修饰的类不能被继承
不允许其子类更改,但可以调用。
如果final前加了private
-
修饰的方法不能被子类重写。
-
修饰的变量(成员变量和局部变量)是常量,只能赋值一次。
-
使用原因:锁定方法,提高效率
>this<
解决命名冲突
1.调用变量**this.attribute**
2.调用方法**this.method()**
3.调用构造方法**this()**
和函数重载知识点紧密结合!!!
形参个数1的重载->调用形参个数2的重载->直到调用最完整的构造方法。这样就利用函数重载的构造方法,用给定最少个数的形参,构造一个初始化的实例,还能减少构造函数重载链的冗余。
| 注意事项 | Why? |
|---|---|
| 禁止递归调用 | 形成递归无限循环❌ |
| 必须是构造方法的第一条语句 | 保证父类先于子类初始化✔ |
| 不能与super()同时使用 |
public Car(String brand, String model, int year, String color) { this.brand = brand; this.model = model; this.year = year; this.color = color; } // 1 public Car(String brand, String model, int year) { this(brand, model, year, "白色"); } // 2 public Car(String brand, String model) { this(brand, model, 2023); } // 3 public Car(String brand) { this(brand, "未知型号"); } // 4 public Car() { this("未知品牌"); }// 调用构造函数4 -> 调用3 -> 调用2 -> 调用1 -> Car("未知品牌","未知型号",2023,"白色")// 简洁代码量的构造传递//即使我给定 形参数最少的构造方法 去实例化一个对象,但这个对象依然具有多个的默认属性。封装
- 实现:用 private 修饰成员变量,通过 public 的 getter/setter 方法访问。
- 目的:隐藏内部实现,只暴露必要接口,提高安全性和可维护性。
访问控制
private:只能在本类访问,不被子类继承可直接访问。default:同包可见。(无访问控制符)protected:同包或子类可见(推荐用于希望子类访问的成员)public:所有地方可见。- 子类的访问权限要比父类更公开、或相同。
- private > default > protected > public
继承
- 单继承:Java类只支持单继承(一个子类只能有一个直接父类),但可通过接口实现多继承效果。
- 关键字:用
extends实现继承,如class Child extends Parent。 - 继承内容:
- 子类继承父类的 非私有成员(字段、方法)。
- 构造器 不被继承,但子类构造器必须(隐式或显式)调用父类构造器。
private成员虽不可见,但依然被继承。
- 父类无构造方法?
- 若父类未定义任何构造方法,编译器会自动提供默认无参构造方法,子类可正常继承(隐式调用
super())。 - 若父类显式定义了任意构造方法(包括有参),则不再生成默认无参构造,此时子类必须显式调用
super(...),否则编译报错。
- 若父类未定义任何构造方法,编译器会自动提供默认无参构造方法,子类可正常继承(隐式调用
- 方法重写(Override):
- 可重写父类非
private、非final、非static的方法。 - 要求:方法名、参数列表、返回类型(协变)一致;访问权限不能更严格。
- 可重写父类非
- super 关键字:
super():调用父类构造器,必须在子类构造器第一行。super.method()/super.field:访问父类成员。super()和this()都必须是构造方法中的第一条语句,所以不能同时出现在同一个构造方法中。
- Object 类:所有类默认继承自
java.lang.Object。 - 初始化顺序: 父类静态块 → 子类静态块 → 父类实例变量/构造块 → 父类构造器 → 子类实例变量/构造块 → 子类构造器。
- final 限制:
final类不能被继承,final方法不能被重写,final字段不能被更改
Object 类:
-
所有类的直接或间接父类。
-
定义类时,未指定他的父类默认继承Object类。
-
Object类的方法:object.tostring()
public class Object { public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); //获取运行时的类的对象的类名@十六进制哈希码 }}//原型 boolean equals(object obj);//浅比较浅比较:比地址相同与否(object.equals()、==)
深比较:比较堆内数据是否相等。
多态
概念
-
Java多态:同一个引用,不同实现。
-
前提:继承 + 方法重写 + 父类引用指向子类对象。
-
表现:编译看左边(父类),运行看右边(实际子类)。
-
目的:提高代码扩展性和可维护性,便于统一处理不同子类。
-
静态多态(编译时多态):
- 通过 方法重载(Overload) 实现。
- 编译器在 编译期 根据参数类型、个数、顺序决定调用哪个方法。
- 与继承无关,同一个类或父子类中都可重载。
-
动态多态(运行时多态):
@Override注解提示编译器要检查- 通过 方法重写(Override) + 父类引用指向子类对象 实现。
- JVM 在 运行期 根据实际对象类型决定调用哪个方法。
- 必须有继承/实现关系,且方法不能是 private/static/final。
函数重载/重写
重写(Override)
- 指子类重新定义父类中已有的方法(方法名、参数列表、返回类型相同),以实现不同的行为。属于运行时多态。
- 子类和父类方法签名必须相同:方法名、参数列表、返回类型
- 子类访问权限不能比父类更低:可以相等或更宽松
- 父类方法:protected修饰 → 子类方法:protected或public ✓
- 父类方法:public修饰 → 子类方法:private ✗
- 不能抛出更宽泛的异常
重载(Overload)
-
指在同一个类中定义多个同名方法,但参数列表不同(参数类型、个数或顺序不同)。属于编译时多态。
-
参数列表不同体现在三个方面:参数类型不同、参数个数不同、参数顺序不同
-
返回值类型(仅返回值不同不构成重载)
-
核心原则:只看方法名和参数列表,其他都不看。 编译器通过参数列表的差异来决定调用哪个重载方法。
对象类型转换:
- 向上转型,将父类引用 -> 子类对象。无需强制转换,此时不能通过父类变量去调子类特有的方法
- 向下转型要 强制转换 最好用
instanceof
Animal animal = new Dog();
animal.eat(); // ✅ 可以调用(如果Dog重写了eat,执行Dog的版本)animal.bark(); // ❌ 编译错误!Animal类没有bark()方法
//需要向下转型才能调用//需要类型判断:`instanceof` 可以判断一个对象是否为某个类的实例if (animal instanceof Dog) { Dog dog = (Dog) animal; // 向下转型 dog.bark(); // ✅ 现在可以调用}抽象类
Contains
- 抽象方法 - (必须显示指定
public abstract) - 其余和普通类所包含一致
Specific
- 抽象类不能被实例化,只能被继承
- 继承该抽象类必须实现抽象类的所有抽象方法
- 抽象类不一定包含抽象方法
- 可以包含成员变量、常量、构造方法(供子类调用)
抽象类 = 有部分实现的模板,需要子类补全; 普通类 = 已完成的功能,你继承它只是为了复用代码。
抽象类的意义是:
让子类一定要干某件事(强制性规范)
接口
接口 相关子类和不相关子类之间抽象出来都具有的行为(约束)。
接口 弥补 了JAVA只能单继承类 ,一个类可以实现多个接口
-
Java 7及之前:完全抽象,只能声明常量和抽象方法
-
Java 8:引入默认方法(default)和静态方法
-
Java 9:引入私有方法
-
常量 - (默认 public static final)
-
抽象方法 - (默认 public abstract) (除该方法,其余均为具体方法)
-
静态方法
-
默认方法
-
私有方法
-
函数式接口
Specific
-
接口也不能实例化,只能被继承
-
继承该接口的子类方法必须实现接口的所有抽象方法
-
默认访问权限是
public abstract(隐式可省) -
接口的所有非私有方法的访问控制权限 均是
public(隐式可省) -
当一个接口是
函数式接口是,只能包含一个抽象方法
Others
Serializable是 标记接口(Marker Interface)-
它没有任何方法
-
只用作标记,告诉 Java “这个类可以被序列化”
-
序列化:把对象的状态(属性值)转换成 字节流,
- 以便:写入文件(永久保存对象状态)
- 通过网络传输对象存入数据库等
-
Lambda表达式
FunctionalInterface
一个注解,提醒编译器检查
Lambda
只能有一个函数式接口的抽象方法供lamda表达式使用
接口上标注有@FunctionalInterface表示该接口是函数式接口,要求编译器严格检查
//这个抽象方法就是lambda要填的空@FunctionalInterfacepublic interface A{ void add(int x,int y);}(int x,int y)->{return x+y;} //匿名方法(x,y)-> x+y;//编译器自动识别数据类型;//一条语句,大括号可以省;//只有一条return,return也可以省//搭配使用A a = (x,y)-> x+20 ;//相当于声明一个匿名类,这个表达式把抽象方法的具体实现定义了,并返回一个对象引用给aSystem.Out.println(a.add(3,4));Functional Interface In Java
<T> 泛型
| 接口 | 方法 | 用途 |
|---|---|---|
Function<T,R> | R apply(T t) | 接受一个参数,返回一个结果 |
Consumer<T> | void accept(T t) | 接受一个参数,不返回结果 |
Supplier<T> | T get() | 不接受参数,返回一个结果 |
Predicate<T> | boolean test(T t) | 接受一个参数,返回布尔值 |
UnaryOperator<T> | T apply(T t) | 接受一个类型参数,返回同类型结果 |
String
Specific
- 不可变性(Immutability)
- String对象一旦创建,其值就不能被修改
- 所有看似修改的操作都返回新的String对象
- 原对象在内存中保持不变
String是final类型(const) 一单创建内容长度不变
StringBuffer可以进行更改
Common Methods
| 方法 | 返回值类型 | 描述 |
|---|---|---|
| 查找相关 | ||
indexOf(String s) | int | 返回第一次找到指定字符串的起始索引 |
indexOf(String s, int fromIndex) | int | 从指定位置开始,返回第一次找到指定字符串的起始索引 |
lastIndexOf(String s) | int | 返回最后一次找到指定字符串的起始索引 |
lastIndexOf(String s, int fromIndex) | int | 从指定位置向前搜索,返回最后一次找到指定字符串的起始索引 |
| 字符访问 | ||
charAt(int index) | char | 返回指定索引处的字符 |
toCharArray() | char[] | 将字符串转换为字符数组 |
| 子字符串操作 | ||
substring(int start, int end) | String | 截取[start, end)范围的子字符串 |
substring(int start) | String | 截取从start到结尾的子字符串 |
| 字符串比较 | ||
equals(Object obj) | boolean | 比较字符串内容是否相等(严格比较) |
equalsIgnoreCase(String s) | boolean | 忽略大小写比较字符串内容 |
compareTo(String anotherString) | int | 按字典顺序比较字符串(区分大小写) |
compareToIgnoreCase(String str) | int | 按字典顺序比较字符串(忽略大小写) |
startsWith(String prefix) | boolean | 测试字符串是否以指定前缀开始 |
endsWith(String suffix) | boolean | 测试字符串是否以指定后缀结束 |
| 字符串连接 | ||
concat(String str) | String | 将指定字符串连接到此字符串的结尾 |
format(String format, Object... args) | String | 使用指定格式字符串和参数格式化字符串 |
join(CharSequence delimiter, CharSequence... elements) | String | 用指定分隔符连接多个字符串(静态方法) |
| 长度和修剪 | ||
length() | int | 返回字符串长度 |
trim() | String | 去除字符串两端的空白字符 |
strip() | String | 去除字符串两端的空白字符(Java 11+,支持更广泛的空白字符) |
isEmpty() | boolean | 检查字符串是否为空(长度是否为0) |
isBlank() | boolean | 检查字符串是否为空或仅包含空白字符(Java 11+) |
| 大小写转换 | ||
toLowerCase() | String | 将字符串转换为小写 |
toUpperCase() | String | 将字符串转换为大写 |
| 替换操作 | ||
replace(char oldChar, char newChar) | String | 替换字符串中的字符 |
replace(CharSequence target, CharSequence replacement) | String | 替换字符串中的子序列 |
replaceAll(String regex, String replacement) | String | 使用正则表达式替换所有匹配的子串 |
replaceFirst(String regex, String replacement) | String | 使用正则表达式替换第一个匹配的子串 |
| 拆分和转换 | ||
split(String regex) | String[] | 根据正则表达式拆分字符串 |
split(String regex, int limit) | String[] | 根据正则表达式拆分字符串,限制拆分次数 |
valueOf(Object obj) | String | 将各种类型的对象转换为字符串表示形式(静态方法) |
| 其他操作 | ||
repeat(int count) | String | 重复字符串指定次数(Java 11+) |
lines() | Stream<String> | 返回字符串中的行流(Java 11+) |
matches(String regex) | boolean | 判断字符串是否匹配给定的正则表达式 |
contains(CharSequence s) | boolean | 判断字符串是否包含指定的字符序列 |
toLowerCase(Locale locale) | String | 使用指定的Locale规则将字符串转换为小写 |
toUpperCase(Locale locale) | String | 使用指定的Locale规则将字符串转换为大写 |
StringBuffer

包装类
将基本数据类型包装成对象的类
所属包:java.lang

1.构造
valueOf()方法 每个原始数据类型包装类都有此方法
Integer num1 = Integer.valueOf(10); // 基本类型Integer num2 = Integer.valueOf("10"); // 字符串Integer num3 = 10;////自动装箱 编译器会转换为 Integer.valueOf(10)被弃用的 直接构造对象方法
Integer num4 = Integer(10)// 在循环中创建大量 Integer 对象时 开销特别大public void processNumbers() { // ❌ 低效 for (int i = 0; i < 1000; i++) { Integer num = new Integer(i); }// 创建1000个不同对象
// ✅ 高效 - 重用缓存对象 for (int i = 0; i < 1000; i++) { Integer num = Integer.valueOf(i); // 对于-128到127的值,重用缓存对象 }}// 缓存范围内的比较Integer a = Integer.valueOf(100);Integer b = Integer.valueOf(100);System.out.println(a == b); // true - 同一个缓存对象
// 缓存范围外的比较Integer c = Integer.valueOf(200);Integer d = Integer.valueOf(200);System.out.println(c == d); // false - 不同对象(大多数情况)实际业务中,很多数字都在缓存范围内 比如:年龄、分数、数量等
Integer age = 25; // 在缓存内Integer score = 85; // 在缓存内Integer quantity = 10; // 在缓存内2.Why?
数据结构这些容器类,必须使用包装类
List<Integer> numbers = new ArrayList<>(); // ✅ 必须用Integer// List<int> numbers = new ArrayList<>(); // ❌ 编译错误泛型必须用包装类
需要null的情况下(从数据库接受null值)
3.parseXXX()
parseXXX() 方法是把字符串转换成基本类型的实用工具。
String numberStr = "123";int number = Integer.parseInt(numberStr);System.out.println(number);// 输出:123(基本类型int)集合框架
包:java.util
-
Collection:单列集合接口
-
List:存取顺序一致性(有序)、可重复、有索引
-
Set:无序、不重复、无索引
-
ArrayList: 基于动态数组实现
-
LinkedList: 基于链表实现
-
Vector: 基于动态数组实现、线程安全
-
-
Map:双列集合接口
Collection接口继承树
Map接口继承树
Collection
| 方法声明 | 描述 |
|---|---|
boolean add(E e) | 添加一个元素 |
boolean remove(Object o) | 删除第一个匹配的元素(按值) |
boolean contains(Object o) | 是否包含某元素 |
int size() | 元素个数 |
boolean isEmpty() | 是否为空 |
void clear() | 清空集合 |
Iterator<E> iterator() | 获取迭代器 |
Object[] toArray() | 转成数组 |
<T> T[] toArray(T[] a) | 转成指定类型数组 |
boolean addAll(Collection<? extends E> c) | 添加另一个集合所有元素 |
boolean removeAll(Collection<?> c) | 删除所有在 c 中出现的元素 |
boolean retainAll(Collection<?> c) | 只保留 c 中也有的元素(求交集) |
boolean containsAll(Collection<?> c) | 是否包含 c 中所有元素 |
List
| 方法声明 | 描述 |
|---|---|
E get(int index) | 获取指定位置元素 |
E set(int index, E element) | 替换指定位置元素 |
void add(int index, E element) | 在指定位置插入单个元素 |
E remove(int index) | 删除指定位置元素 |
boolean addAll(int index, Collection<? extends E> c) | 在指定位置插入整个集合 |
int indexOf(Object o) | 第一次出现的索引 |
int lastIndexOf(Object o) | 最后一次出现的索引 |
ListIterator<E> listIterator() | 双向迭代器 |
ListIterator<E> listIterator(int index) | 从指定位置开始的双向迭代器 |
List<E> subList(int fromIndex, int toIndex) | 返回子列表视图 |
Set
- 所有 Set 实现类支持的方法,就是
Collection的全部方法
| 方法声明 | 在 Set 中的特殊行为 |
|---|---|
boolean add(e) | 如果 e 已存在(通过 equals() 判断),插入失败,返回 false |
boolean addAll(c) | 自动跳过重复元素,只加入不重复的 |
| 元素唯一性 | 由 equals() + hashCode()(HashSet/LinkedHashSet)或 compareTo()(TreeSet)保证 |
LinkedList
| 方法声明 | 描述 | 异常 |
|---|---|---|
void addFirst(E e) | 在头部插入元素 | 失败抛异常(如内存溢出) |
void addLast(E e) | 在尾部插入元素 | 失败抛异常 |
E getFirst() | 获取头部元素(不删除) | 空时抛 NoSuchElementException |
E getLast() | 获取尾部元素(不删除) | 空时抛 NoSuchElementException |
boolean offer(E e) | 入队(等价于 offerLast(e)) | 成功返回 true,失败返回 false |
boolean offerFirst(E e) | 在头部插入元素 | 成功返回 true,失败返回 false |
boolean offerLast(E e) | 在尾部插入元素 | 成功返回 true,失败返回 false |
E peek() | 查看队首(等价于 peekFirst()) | 空时返回 null |
E peekFirst() | 获取头部元素(不删除) | 空时返回 null |
E peekLast() | 获取尾部元素(不删除) | 空时返回 null |
E poll() | 出队(等价于 pollFirst()) | 空时返回 null |
E pollFirst() | 删除并返回头部元素 | 空时返回 null |
E pollLast() | 删除并返回尾部元素 | 空时返回 null |
E pop() | 弹栈(等价于 removeFirst()) | 空时抛 NoSuchElementException |
void push(E e) | 压栈(等价于 addFirst(e)) | 抛异常 |
E removeFirst() | 删除并返回头部元素 | 空时抛 NoSuchElementException |
E removeLast() | 删除并返回尾部元素 | 空时抛 NoSuchElementException |
Map
| 方法声明 | 描述 |
|---|---|
void clear() | 清空所有键值对 |
void putAll(Map<? extends K, ? extends V> m) | 批量插入另一个 Map 的所有键值对 |
boolean containsKey(Object key) | 判断是否包含指定 key |
boolean containsValue(Object value) | 判断是否包含指定 value |
boolean isEmpty() | 判断 Map 是否为空(size == 0) |
int size() | 返回键值对数量 |
V get(Object key) | 根据 key 获取 value,不存在返回 null |
V put(K key, V value) | 插入/更新键值对,返回旧 value(无则返回 null) |
V remove(Object key) | 删除 key 对应的键值对,返回被删的 value |
Set<K> keySet() | 返回所有 key 的 Set 视图 |
Collection<V> values() | 返回所有 value 的 Collection 视图 |
Set<Map.Entry<K, V>> entrySet() | 返回所有键值对(Entry)的 Set 视图 |
Map.Entry<K, V>
| 方法声明 | 描述 |
|---|---|
K getKey() | 返回此键值对中的 键(key) |
V getValue() | 返回此键值对中的 值(value) |
V setValue(V value) | 替换此键值对中的值,返回 旧值** |
异常处理机制
异常
- 程序运行中,发生不正常的,破坏程序执行流程的事件;
类型
- 编译型异常(checked)
- 运行时异常(unchecked):编译器不检查,可处理;RuntimeException也是此类异常
异常类
| 异常类名称 | 异常原因 |
|---|---|
| ArithmeticException | 算数异常,如被零除发生的异常 |
| ArrayIndexOutOfBoundsException | 数组下标越界 |
| ArrayStoreException | 程序试图在数组中存储错误类型的数据 |
| ClassCastException | 类型强制转换异常 |
| IndexOutOfBoundsException | 当某对象的索引超出范围时抛出异常 |
| NegativeArraySizeException | 建立元素个数为负数的数组异常 |
| NullPointerException | 空指针异常 |
| NumberFormatException | 字符串转换为数字异常 |
| StringIndexOutOfBoundsException | 程序试图访问字符串中不存在的字符位置 |
| OutOfMemoryException | 分配给新对象的内存太少 |
| SocketException | 不能正常完成Socket操作 |
| ProtocolException | 网络协议有错误 |
| ClassNotFoundException | 未找到相应异常 |
| EOFException | 文件结束异常 |
| FileNotFoundException | 文件未找到异常 |
| IllegalAccessException | 访问某类被拒绝时抛出的异常 |
| InstantiationException | 试图通过newInstance()方法创建一个抽象类或抽象接口的实例时抛出该异常 |
| IOException | 输入输出异常 |
| NoSuchMethodException | 方法未找到异常 |
| SQLException | 操作数据库异常 |
异常处理
关键字
- try:放可能出错的代码
- catch:捕获特定类型的异常并处理
- finally:清理资源,一定会执行(除非 System.exit(0))
结构
-
try……catch……finally结构
-
try……with……resources结构
-
throws
方法不靠谱时,可以设计向上一级函数抛出异常类
格式:方法名() throws 异常类列表
- throw
手动抛出一个对象类
public void method() throws Exception{ if(...) {....} else{ throw new Exception("sth wrong here"); }}//这个方法可能会不符合程序设计需求,需要手动抛出一个异常,由上级函数捕获自定义异常类
extend异常父类即可 + throw
多线程
创建&运行
- 创建一个新的类继承
Thread,重写run()
MyThread thread1 = new Mythread();Mythread.start();- 创建一个新的类继承
Runnable,重写run()- 并将该类传入
Thread构造器 Thread构造里里有Runnable类型参数,传入继承runnable的子类调用run(),是可以的run()是抽象方法,Runnable是函数式接口所以可以用Lamda简化
- 并将该类传入
Runnable runnable = () -> System.out.println("It's a task");Thread thread2 = new Thread(runnable);thread2.start();异步
- 主线程 和 子线程 是异步执行的
Thread thread1 = new Thread(()->{ System.out.println("thread1");});Thread thread2 = new Thread(()->{ System.out.println("thread2");}); thread1.start(); thread2.start(); System.out.println(Thread.currentThread().getName());join
- join()方法用于让当前线程等待调用join()方法的线程执行完毕后再继续执行。
- 阻塞的永远是调用
join的线程
Thread thread1 = new Thread(()->{ System.out.println("thread1");});thread1.start();System.out.println("Main thread is waiting for Thread2");try{ thread1.join();}catch(Exception e){ System.out.println(e.getMessage());};System.out.println("Main thread is finished");网络编程
InetAddress类
-
用于封装一个IP地址,并提供一系列与IP地址相关的方法
-
host:可以是域名、ip地址、特殊地址(localhost 127.0.0.1)

UDP
DatagramPacket类
Java 中用于 UDP 网络编程的核心类,是封装发送数据、存储接收数据和地址信息的数据单元。
以下是常用构造方法:
接收端
//`buf`接受数据的缓冲区,`length` 读取的数据最大长度public DatagramPacket(byte[] buf, int length)//`offset` 在缓冲区中的偏移位置offset接收数据public DatagramPacket(byte[] buf, int offset, int length)发送端
//`address` 目标 IP 地址 `port` 目标端口号public DatagramPacket(byte[] buf, int length, InetAddress address, int port)//`offset` 在缓冲区中的偏移 `offset`位置发送数据public DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)Common Methods

DatagramSocket
Java 中用于 UDP 网络编程的核心类,是UDP网络通信的端点, 负责传输数据
接收端
//`port` 指定一个端口 用于 监听new DatagramSocket(int port)发送端
//系统自动分配没有被其他网络程序所使用的端口号new DatagramSocket()多块网卡
//用于计算机有多块网卡的情况,明确数据通过哪块网卡向外发送和接收哪块网卡的数据new DatagramSocket(int port, InetAddress address)Common Methods

Concludes
1.接收端指定 DatagramSocket 监听端口
2.发送端指定 接收端IP地址、端口
DatagramSocket- 菜鸟驿站
DatagramPacket- 打包货车
byte[]数组 - 实际数据形式1.声明接收端和发送端的 socket端
接收端 指明 监听端口
2.设置收发端Packet
作为发送端要指明 —> 传输的数据byte[] -> 接收端的IP地址和端口
作为接收端要指明 —> 接收的数据解包放在byte[] -> 无需IP地址和端口
最后菜鸟驿站Socket 派指定 货车Packet 出发 - send() 另外一个菜鸟驿站Socket 接收 货车Packet - receive()
JDBC
含义
Java JDBC(Java Database Connectivity)是一套用于连接和操作关系型数据库的 Java API。它提供了一组接口和类,使 Java 应用程序能够与各种数据库进行交互。迁移数据时,不需要大量更改代码
不同数据库的不同驱动

访问步骤
- 加载数据库驱动
- 建立连接
DriverManager.getConnection() - 创建连接对象
- 创建语句对象
- 执行sql语句获取执行结果
- 关闭连接(先开后关)

注解
概念
注解(Annotation):贴在代码上的“标签”,可以被编译器、框架或工具读取的特殊备注。
-
格式:@注解名
-
作用范围:package、class、method、field
-
访问:可以通过反射机制对这些元数据访问
内置注解
- 包:java.lang
| 注解 | 作用 | 使用位置 | 是否保留到运行时 |
|---|---|---|---|
@Override | 表示当前方法重写了父类的方法。如果父类没有这个方法,编译会报错,帮你避免写错。 | 方法上 | 否(只在编译期有效) |
@Deprecated | 表示某个类、方法或字段已过时,不推荐使用。使用时编译器会警告你。 | 类 / 方法 / 字段 | 是(保留到运行时) |
@SuppressWarnings | 抑制编译器警告。比如你用了不安全的泛型操作,可以用它关掉警告。 | 类 / 方法 / 字段 / 局部变量 | 否 |
@FunctionalInterface | 表示这是一个函数式接口(只能有一个抽象方法)。如果不是,编译报错。 | 接口上 | 否 |
@SafeVarargs | 用于可变参数方法,告诉编译器“我知道有泛型风险,但我保证安全”,从而消除警告。 | 方法 / 构造器 | 否 |
@SuppressWarnings参数
| 参数值 | 作用说明 |
|---|---|
"unchecked" | 忽略泛型未检查转换警告(如 List list = new ArrayList();) |
"deprecation" | 忽略使用了 @Deprecated 过时代码的警告 |
"rawtypes" | 忽略使用原始类型(如 List 而不是 List<String>) |
"unused" | 忽略未使用的变量、方法、参数等 |
"fallthrough" | 忽略 switch 中 case 穿透(无 break)警告 |
"serial" | 忽略可序列化类缺少 serialVersionUID 的警告 |
"all" | idea自带,不推荐 |
元注解
包:java.lang.annotation
@Retention
作用:指定注解保留到哪个阶段。
参数类型:RetentionPolicy
| 参数值 | 含义 | 是否可通过反射获取 |
|---|---|---|
RetentionPolicy.SOURCE | 只在源代码中存在,编译时丢弃 | 不能 |
RetentionPolicy.CLASS | 编译后保留在 .class 文件中,但 JVM 不加载 | 不能(默认值) |
RetentionPolicy.RUNTIME | 保留在运行时,JVM 加载后可用 | 能(常用) |
示例:
@Target
作用:限制注解能标注在哪些程序元素上。
参数类型:ElementType[](数组,可写多个)
| 参数值 | 可标注的位置 |
|---|---|
ElementType.TYPE | 类、接口、注解、枚举 |
ElementType.FIELD | 字段(成员变量) |
ElementType.METHOD | 方法 |
ElementType.PARAMETER | 方法参数 |
ElementType.CONSTRUCTOR | 构造方法 |
ElementType.LOCAL_VARIABLE | 局部变量 |
ElementType.ANNOTATION_TYPE | 注解类型本身(用于元注解) |
ElementType.PACKAGE | 包(需配合 package-info.java 使用) |
ElementType.TYPE_PARAMETER | 类型参数(Java 8+,如 class MyClass<T> 中的 T) |
ElementType.TYPE_USE | 任何类型使用处(Java 8+,如 List<@My String>) |
示例:
@Target({ElementType.METHOD, ElementType.FIELD})
@Documented
作用:是否在生成 JavaDoc 时包含该注解。 参数:无参数(标记型注解)
@Inherited
作用:父类的注解是否被子类继承(仅对类有效)。 参数:无参数(标记型注解)
@Repeatable
作用:允许同一个地方多次使用同一个注解。
参数:value(必须指定一个“容器注解”的 class)
| 参数名 | 类型 | 说明 |
|---|---|---|
value | Class<? extends Annotation> | 指定一个“容器注解”,用于存放重复的注解 |
自定义注解
- 1个参数,名为value,使用注解可以不给参数名
- default参数默认值:不显式声明时使用
@元注解public @interface 注解名{ //注解参数: 类型 参数名() default 默认值;}反射
概念
-
静态语言:运行时代码能改变自身结构(Java、C、C++)
-
动态语言:运行时代码不能改变自身结构(C#、JavaScript、Python)
-
反射:程序运行期间,动态获取类的结构信息(类名、构造器、方法、字段、注解等),并对其进行操作(创建对象、调用方法、访问字段)。
-
Java:通过反射机制成为准动态语言
Class
包:java.lang.Class、java.lang.reflect
- 动态获取类的结构信息通过Class类
- Class 本身也是一个类
- Class 对象只能由系统建立对象
- 一个加载的类在 JVM 中只会有一个 Class 实例
- 一个 Class 对象对应的是一个加载到 JVM 中的一个 class 文件
- 每个类的实例都会记得自己是由哪个 Class 实例所生成
- 通过 Class 可以完整地得到一个类中的所有被加载的结构
- Class 类是 Reflection 的根源,针对任何你想动态加载、运行的类,唯有先获得相应的 Class 对象
四种方式获取:
// 1. 通过类名(最常用,最灵活)Class<?> c1 = Class.forName("com.example.User");
// 2. 通过类.class(编译期已知)Class<User> c2 = User.class;
// 3. 通过对象.getClass()User u = new User();Class<? extends User> c3 = u.getClass();
// 4. 包装类通过TYPE属性Class c4 = Integer.TYPE;| 方式 | 返回类型 | 类型是否已知 | 是否触发类初始化 | 使用场景 | 注意事项 |
|---|---|---|---|---|---|
Class.forName() | Class<?> | 运行时才知道 | 执行 static 块 | 动态加载、配置文件、框架反射 | 必须类在 classpath;要写全限定名;可能抛 ClassNotFoundException |
类名.class | Class<User> | 编译期已知 | 不会触发 | 编译时确定的类;泛型安全 | 最安全高效;不能用于动态类名 |
对象.getClass() | Class<? extends User> | 运行时真实类型 | 类必须已加载 | 多态场景;获取实际类型 | 返回的是实际类型,可能是子类 |
包装类 .TYPE | Class<Integer> | 已知 | 不触发 | 获取基本类型对应的 Class | Integer.TYPE == int.class,不是 Integer.class |
常用方法
获取类信息
c1.getName(); // 全限定名c1.getSimpleName(); // 类名c1.getSuperclass(); // 父类c1.getInterfaces(); // 接口c1.getAnnotations(); // 注解示例
class User { private String name;
private User(String name) { this.name = name; }
private void hello() { System.out.println("Hello " + name); }}
// 反射使用Class<?> clazz = Class.forName("User");
// 创建对象Constructor<?> con = clazz.getDeclaredConstructor(String.class);con.setAccessible(true);Object obj = con.newInstance("Tom");
// 调用方法Method m = clazz.getDeclaredMethod("hello");m.setAccessible(true);m.invoke(obj);优缺点
-
高度灵活,解耦严重依赖
-
支持运行时扩展
-
是大型框架的基础
-
性能较低(绕过编译期优化)
-
破坏封装性
-
编译期无法检查错误
-
代码可读性、可维护性下降
结论: 业务代码慎用,框架代码必用
对比
| 对比项 | new | 反射 |
|---|---|---|
| 编译期检查 | 有 | 无 |
| 性能 | 高 | 低 |
| 灵活性 | 低 | 高 |
| 是否依赖类名字符串 | 否 | 是 |
未学习的,重要的点
注释
深浅比较
正则表达式
网络编程
八股
构造方法 vs 普通方法
-
名字不同
- 构造方法名必须和类名完全相同。
- 普通方法名不能和类名相同(虽然技术上可以,但强烈不建议,且不是构造方法)。
-
返回值类型
- 构造方法没有返回值类型,连
void都不能写。 - 普通方法必须有返回值类型(包括
void)。
- 构造方法没有返回值类型,连
-
调用时机
- 构造方法在创建对象时自动调用(用
new时)。 - 普通方法需要通过对象显式调用(如
obj.method())。
- 构造方法在创建对象时自动调用(用
-
作用不同
- 构造方法用于初始化对象(比如给成员变量赋初值)。
- 普通方法用于实现具体功能(比如计算、打印等)。
-
能否被继承/重写
- 构造方法不能被继承,也不能被重写(override)。
- 普通方法可以被继承和重写。
重写 vs 重载
-
发生位置不同
-
重载:发生在同一个类中。
-
重写:发生在子类和父类之间。
-
-
方法签名要求不同
-
重载:方法名相同,但参数列表不同(参数类型、个数、顺序至少一个不同)。返回值可以不同,但不能仅靠返回值不同来重载。
-
重写:方法名、参数列表必须完全相同。返回值类型也必须相同或是其子类型(协变返回)。
-
-
访问修饰符
-
重载:无特别限制。
-
重写:子类方法的访问权限不能比父类更严格(比如父类是
protected,子类不能是private)。
-
-
是否涉及多态
-
重载:属于编译时多态(静态绑定),编译器根据参数决定调用哪个方法。
-
重写:属于运行时多态(动态绑定),JVM 在运行时根据对象实际类型决定调用哪个方法。
-
接口 vs 抽象类
| 区别 | 接口 | 抽象类 |
|---|---|---|
| 继承 | 多实现(可实现多个接口) | 单继承 |
| 方法类型 | 抽象、默认、静态、私有 | 抽象、具体 |
| 字段 | 只有常量(public static final) | 可以有变量 |
| 构造器 | 无 | 在子类创建对象时会被调用 |
| 访问修饰符 | 默认 public | 任意 |
| 设计目的 | 定义能力/行为契约 | 定义通用模板 |
字节流 vs 字符流
部分信息可能已经过时