7817 字
21 分钟
Java基础

面向对象的语言:

  • 封装:封装是将对象的属性和行为封装起来,不需要让外界知道具体实现细节;
  • 继承:继承是可以在无需重新编写原有类的情况下,对原有类的功能进行扩展;
  • 多态:多态指的是在一个类中定义的属性和功能被其他类继承后,当把子类对象直接赋值给父类引用变量时,相同引用类型的变量调用同一个方法所呈现出的多种不同行为特性

技术平台:Java EEJava SEJava 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. 典型应用工具方法、常量、单例、计数器对象属性、业务方法、状态操作

执行顺序

  1. 父类静态 → 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

继承#

  1. 单继承:Java类只支持单继承(一个子类只能有一个直接父类),但可通过接口实现多继承效果。
  2. 关键字:用 extends 实现继承,如 class Child extends Parent
  3. 继承内容
    • 子类继承父类的 非私有成员(字段、方法)。
    • 构造器 不被继承,但子类构造器必须(隐式或显式)调用父类构造器。
    • private 成员虽不可见,但依然被继承。
  4. 父类无构造方法?
    • 若父类未定义任何构造方法,编译器会自动提供默认无参构造方法,子类可正常继承(隐式调用 super())。
    • 若父类显式定义了任意构造方法(包括有参),则不再生成默认无参构造,此时子类必须显式调用 super(...),否则编译报错。
  5. 方法重写(Override)
    • 可重写父类非 private、非 final、非 static 的方法。
    • 要求:方法名、参数列表、返回类型(协变)一致;访问权限不能更严格。
  6. super 关键字
    • super():调用父类构造器,必须在子类构造器第一行。
    • super.method() / super.field:访问父类成员。
    • super()this() 都必须是构造方法中的第一条语句,所以不能同时出现在同一个构造方法中。
  7. Object 类:所有类默认继承自 java.lang.Object
  8. 初始化顺序: 父类静态块 → 子类静态块 → 父类实例变量/构造块 → 父类构造器 → 子类实例变量/构造块 → 子类构造器。
  9. 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要填的空
@FunctionalInterface
public 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 ;//相当于声明一个匿名类,这个表达式把抽象方法的具体实现定义了,并返回一个对象引用给a
System.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#

image-20251114152000043

包装类#

将基本数据类型包装成对象的类

所属包:java.lang

image-20251031141420849

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:双列集合接口

imgCollection接口继承树

imgMap接口继承树

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)

image-20251209115011810

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#

image-20251209195539968

DatagramSocket#

Java 中用于 UDP 网络编程的核心类,是UDP网络通信的端点, 负责传输数据

接收端#

//`port` 指定一个端口 用于 监听
new DatagramSocket(int port)

发送端#

//系统自动分配没有被其他网络程序所使用的端口号
new DatagramSocket()

多块网卡#

//用于计算机有多块网卡的情况,明确数据通过哪块网卡向外发送和接收哪块网卡的数据
new DatagramSocket(int port, InetAddress address)

Common Methods#

image-20251209195458200

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 应用程序能够与各种数据库进行交互。迁移数据时,不需要大量更改代码

不同数据库的不同驱动

image-20251216104900773

访问步骤#

  1. 加载数据库驱动
  2. 建立连接 DriverManager.getConnection()
  3. 创建连接对象
  4. 创建语句对象
  5. 执行sql语句获取执行结果
  6. 关闭连接(先开后关)

还没读完

image-20251219153741704

注解#

概念#

注解(Annotation):贴在代码上的“标签”,可以被编译器、框架或工具读取的特殊备注。

  • 格式:@注解名

  • 作用范围packageclassmethodfield

  • 访问可以通过反射机制对这些元数据访问

内置注解#

  • 包: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)

参数名类型说明
valueClass<? extends Annotation>指定一个“容器注解”,用于存放重复的注解

自定义注解#

  • 1个参数,名为value,使用注解可以不给参数名
  • default参数默认值:不显式声明时使用
@元注解
public @interface 注解名{
//注解参数:
类型 参数名() default 默认值;
}

反射#

概念#

  • 静态语言:运行时代码能改变自身结构(Java、C、C++)

  • 动态语言:运行时代码不能改变自身结构(C#、JavaScript、Python)

  • 反射:程序运行期间,动态获取类的结构信息(类名、构造器、方法、字段、注解等),并对其进行操作(创建对象、调用方法、访问字段)。

  • Java:通过反射机制成为准动态语言


Class#

包:java.lang.Classjava.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
类名.classClass<User>编译期已知不会触发编译时确定的类;泛型安全最安全高效;不能用于动态类名
对象.getClass()Class<? extends User>运行时真实类型类必须已加载多态场景;获取实际类型返回的是实际类型,可能是子类
包装类 .TYPEClass<Integer>已知不触发获取基本类型对应的 ClassInteger.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);

优缺点#

  1. 高度灵活,解耦严重依赖

  2. 支持运行时扩展

  3. 是大型框架的基础

  4. 性能较低(绕过编译期优化)

  5. 破坏封装性

  6. 编译期无法检查错误

  7. 代码可读性、可维护性下降

结论: 业务代码慎用,框架代码必用


对比#

对比项new反射
编译期检查
性能
灵活性
是否依赖类名字符串

#

未学习的,重要的点#

注释

深浅比较

正则表达式

网络编程

八股#

构造方法 vs 普通方法#

  1. 名字不同

    • 构造方法名必须和类名完全相同。
    • 普通方法名不能和类名相同(虽然技术上可以,但强烈不建议,且不是构造方法)。
  2. 返回值类型

    • 构造方法没有返回值类型,连 void 都不能写。
    • 普通方法必须有返回值类型(包括 void)。
  3. 调用时机

    • 构造方法在创建对象时自动调用(用 new 时)。
    • 普通方法需要通过对象显式调用(如 obj.method())。
  4. 作用不同

    • 构造方法用于初始化对象(比如给成员变量赋初值)。
    • 普通方法用于实现具体功能(比如计算、打印等)。
  5. 能否被继承/重写

    • 构造方法不能被继承,也不能被重写(override)。
    • 普通方法可以被继承和重写。

重写 vs 重载#

  1. 发生位置不同

    • 重载:发生在同一个类中

    • 重写:发生在子类和父类之间

  2. 方法签名要求不同

    • 重载:方法名相同,但参数列表不同(参数类型、个数、顺序至少一个不同)。返回值可以不同,但不能仅靠返回值不同来重载。

    • 重写:方法名、参数列表必须完全相同。返回值类型也必须相同或是其子类型(协变返回)。

  3. 访问修饰符

    • 重载:无特别限制。

    • 重写:子类方法的访问权限不能比父类更严格(比如父类是 protected,子类不能是 private)。

  4. 是否涉及多态

    • 重载:属于编译时多态(静态绑定),编译器根据参数决定调用哪个方法。

    • 重写:属于运行时多态(动态绑定),JVM 在运行时根据对象实际类型决定调用哪个方法。

接口 vs 抽象类#

区别接口抽象类
继承多实现(可实现多个接口)单继承
方法类型抽象、默认、静态、私有抽象、具体
字段只有常量(public static final可以有变量
构造器在子类创建对象时会被调用
访问修饰符默认 public任意
设计目的定义能力/行为契约定义通用模板

字节流 vs 字符流#

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Java基础
https://mizuki.mysqil.com/posts/java基础/
作者
Oddpalmer
发布于
2026-01-22
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时