当前位置: 首页 > ai >正文

Java面向对象(OOP)终极指南:从基础到高级应用

一、面向对象编程基础概念

面向对象编程(Object-Oriented Programming, OOP)是一种编程范式,它使用"对象"来设计应用程序和计算机程序。Java是一种纯面向对象的语言。

1.1 四大基本特性

特性描述生活类比
封装将数据和行为包装在一个单元中,隐藏内部实现细节就像电视机,我们只需要知道如何使用遥控器,不需要了解内部电路
继承子类继承父类的特征和行为类似父子关系,孩子继承父母的一些特征
多态同一操作作用于不同对象,可以有不同的解释就像"吃饭"这个动作,人和动物吃饭的方式不同
抽象提取关键特征而忽略非本质细节就像地图,只显示重要信息而忽略不相关细节

1.2 类与对象

是对象的蓝图或模板,对象是类的实例。

想象你要造汽车:

  • 就是汽车的设计图纸,上面规定了汽车要有轮胎、方向盘、发动机等部件,还能跑、能停
  • 对象就是根据这张图纸造出来的具体汽车,比如你家那辆红色丰田,邻居家的黑色宝马
// 定义一个"汽车"类
public class Car {// 属性(成员变量)String brand;  // 品牌String color;  // 颜色int maxSpeed;  // 最高速度// 方法void drive() {System.out.println(color + "的" + brand + "正在行驶,最高时速:" + maxSpeed + "km/h");}void brake() {System.out.println(brand + "正在刹车");}
}// 创建对象并使用
public class Main {public static void main(String[] args) {// 创建Car类的实例(对象)Car myCar = new Car();// 设置属性myCar.brand = "丰田";myCar.color = "红色";myCar.maxSpeed = 180;// 调用方法myCar.drive();  // 输出: 红色的丰田正在行驶,最高时速:180km/hmyCar.brake();  // 输出: 丰田正在刹车}
}

二、面向对象核心概念详解

2.1 封装与访问控制

想象一个自动售货机:

  • 你只需要按按钮选择商品(公开的方法)
  • 不需要知道机器内部怎么计算找零、怎么出货(隐藏的实现细节)
  • 更不能直接伸手进去拿钱(保护内部数据)

封装的核心在于保护数据,通过访问修饰符控制访问级别:

修饰符类内同包子类任意位置
private
(default)
protected
public

良好封装实践:

public class BankAccount {// 私有属性,外部不能直接访问private String accountNumber;private double balance;// 公开的构造方法public BankAccount(String accountNumber, double initialBalance) {this.accountNumber = accountNumber;this.balance = initialBalance;}// 公开的方法用于访问和修改私有属性public double getBalance() {return balance;}public void deposit(double amount) {if (amount > 0) {balance += amount;System.out.println("存款成功,当前余额: " + balance);} else {System.out.println("存款金额必须大于0");}}public void withdraw(double amount) {if (amount > 0 && amount <= balance) {balance -= amount;System.out.println("取款成功,当前余额: " + balance);} else {System.out.println("取款金额无效或余额不足");}}
}// 使用示例
public class Main {public static void main(String[] args) {BankAccount account = new BankAccount("123456789", 1000);account.deposit(500);  // 存款成功,当前余额: 1500.0account.withdraw(200); // 取款成功,当前余额: 1300.0// account.balance = 1000000; // 错误!balance是私有的,不能直接访问}
}

2.2 继承与多态

继承:就像“父子遗传”

儿子继承老爸:

  • 儿子天生就有老爸的眼睛颜色、血型(继承属性)
  • 儿子会老爸教的开車技术(继承方法)
  • 儿子还可以有自己的特长,比如会编程(扩展新方法)
  • 儿子可以改进老爸的做菜方法,做得更好吃(方法重写)
// 父类
class Animal {String name;public Animal(String name) {this.name = name;}public void eat() {System.out.println(name + "正在吃东西");}public void sleep() {System.out.println(name + "正在睡觉");}
}// 子类继承父类
class Dog extends Animal {String breed;  // 狗特有的属性public Dog(String name, String breed) {super(name);  // 调用父类构造方法this.breed = breed;}// 子类特有的方法public void bark() {System.out.println(name + "(" + breed + ")在汪汪叫");}// 方法重写(Override)@Overridepublic void eat() {System.out.println(name + "正在狼吞虎咽地吃狗粮");}
}// 使用示例
public class Main {public static void main(String[] args) {Animal animal = new Animal("普通动物");animal.eat();  // 普通动物正在吃东西Dog dog = new Dog("阿黄", "金毛");dog.eat();     // 阿黄正在狼吞虎咽地吃狗粮 (重写后的方法)dog.sleep();   // 阿黄正在睡觉 (继承自父类)dog.bark();    // 阿黄(金毛)在汪汪叫 (子类特有方法)}
}
多态:就像“同一句话对不同对象有不同效果”

"表演才艺"这句话:

  • 对歌手来说是"唱歌"
  • 对舞者是"跳舞"
  • 对魔术师是"变魔术"
class Actor {void performTalent() { System.out.println("演员表演"); }
}class Singer extends Actor {@Overridevoid performTalent() { System.out.println("唱一首歌"); }
}class Dancer extends Actor {@Overridevoid performTalent() { System.out.println("跳一支舞"); }
}public class Party {public static void main(String[] args) {Actor[] Actors = {new Singer(), new Dancer()};for(Actor t : Actors) {t.performTalent(); // 歌手会唱歌// 舞者会跳舞}}
}public class Main {public static void main(String[] args) {// 多态:父类引用指向子类对象Animal myAnimal;myAnimal = new Cat();myAnimal.makeSound();  // 输出: 喵喵喵myAnimal = new Bird();myAnimal.makeSound(); // 输出: 叽叽喳喳// myAnimal.fly();     // 错误!Animal类没有fly方法// 正确的向下转型if (myAnimal instanceof Bird) {Bird myBird = (Bird) myAnimal;myBird.fly();      // 输出: 鸟儿在飞翔}}// 多态在方法参数中的应用public static void animalSound(Animal animal) {animal.makeSound();}
}

我也写了一篇关于多态的详细分析,请查看…

2.3 抽象类与接口

2.3.1 抽象类:不完整的蓝图

专业定义:抽象类是用abstract修饰的类,它不能被实例化,可能包含抽象方法(没有实现的方法)和具体方法(有实现的方法)。

通俗理解:想象抽象类就像一个不完整的汽车设计图 - 它定义了汽车的基本结构(车轮、发动机等),但某些部件(如发动机的具体型号)没有完全确定,需要后续具体车型来完善。

**例如:**去餐厅吃饭:

  • 菜单告诉你有什么菜(抽象方法)
  • 你不用关心厨师怎么做菜(隐藏实现细节)
  • 不同餐厅的同一道菜做法可能不同(不同实现)
// 抽象类示例:交通工具
abstract class Vehicle {// 具体字段protected String brand;// 构造方法public Vehicle(String brand) {this.brand = brand;}// 具体方法public void start() {System.out.println(brand + "启动中...");}// 抽象方法 - 没有实现public abstract void run();// 具体方法public void stop() {System.out.println(brand + "已停止");}
}
2.3.2 接口:纯粹的行为契约

专业定义:接口是完全抽象的引用类型,定义了一组方法签名(Java 8前),可以包含常量(public static final)。

通俗理解:接口就像一份技能证书 - 它证明某个对象"能做什么"(如会游泳、会飞行),但不关心对象具体是什么或如何实现这些能力。

**例如:**电器和插座:

  • 插座规定必须是两脚扁插(接口定义规范)
  • 不管什么电器(电视/电脑),只要符合插头标准就能用(实现接口)
  • 一个电器可以有多个插头(实现多个接口),比如既能USB充电又能插插座
// 插座接口
interface TwoPinSocket {void plugIntoTwoPinSocket();
}
// USB接口
interface USBInterface {void plugIntoUSB();
}// 手机实现两种接口
class MobilePhone implements TwoPinSocket, USBInterface {@Overridepublic void plugIntoTwoPinSocket() {System.out.println("用充电器充电");}@Overridepublic void plugIntoUSB() {System.out.println("用USB线连电脑");}
}    
2.3.3 抽象类 vs 接口对比
维度抽象类接口
关键字abstract classinterface
实例化不能直接实例化不能直接实例化
方法类型抽象方法和具体方法Java 8前只有抽象方法,之后有默认/静态/私有方法
变量类型任意类型变量只能是public static final常量
构造方法
继承/实现单继承(extends)多实现(implements)
设计理念“是什么”(is-a)关系“能做什么”(can-do)关系
访问修饰符任意方法默认public
版本兼容性新增方法影响子类Java 8+默认方法不影响实现类
典型用途代码复用,部分实现定义行为契约,多态
2.3.4 何时使用抽象类 vs 接口

使用抽象类的情况

  • 多个相关类需要共享代码
  • 需要定义非静态/非final字段
  • 需要控制访问权限(非public)
  • 需要定义构造方法或初始化逻辑

使用接口的情况

  • 不相关类需要实现相同行为
  • 需要多重继承行为
  • 定义API契约
  • 希望实现类保持灵活性

三、高级面向对象特性

3.1 内部类

内部类类型特点使用场景
成员内部类定义在类中,方法外,可以访问外部类的所有成员当类只被一个外部类使用时
静态内部类用static修饰的成员内部类,只能访问外部类的静态成员不需要访问外部类实例时
方法内部类定义在方法中,作用域限于方法内只在某个方法中使用
匿名内部类没有名字的内部类,通常用于实现接口或继承类一次性使用的简单实现

示例代码:

// 外部类
class Computer {private String brand;private CPU cpu;public Computer(String brand) {this.brand = brand;this.cpu = new CPU("Intel i7"); // 创建内部类实例}// 成员内部类class CPU {private String model;public CPU(String model) {this.model = model;}public void process() {// 可以访问外部类的私有成员System.out.println(brand + "电脑的CPU " + model + " 正在处理数据");}}public void start() {cpu.process();// 方法内部类class Memory {void load() {System.out.println("内存加载中...");}}Memory memory = new Memory();memory.load();}// 静态内部类static class Keyboard {static void input() {System.out.println("键盘输入");// System.out.println(brand); // 错误!不能访问非静态成员}}// 使用匿名内部类实现接口interface Display {void show();}Display getDisplay() {return new Display() {@Overridepublic void show() {System.out.println(brand + "显示器正在显示");}};}
}// 使用示例
public class Main {public static void main(String[] args) {Computer computer = new Computer("联想");computer.start();// 输出:// 联想电脑的CPU Intel i7 正在处理数据// 内存加载中...Computer.Keyboard.input(); // 键盘输入Computer.Display display = computer.getDisplay();display.show(); // 联想显示器正在显示}
}

3.2 枚举类

枚举是一种特殊的类,用于定义一组常量。

// 定义枚举
enum Day {MONDAY("星期一", 1),TUESDAY("星期二", 2),WEDNESDAY("星期三", 3),THURSDAY("星期四", 4),FRIDAY("星期五", 5),SATURDAY("星期六", 6),SUNDAY("星期日", 7);private String chinese;private int number;// 枚举可以有构造方法private Day(String chinese, int number) {this.chinese = chinese;this.number = number;}// 可以有方法public String getChinese() {return chinese;}public int getNumber() {return number;}public boolean isWeekend() {return this == SATURDAY || this == SUNDAY;}
}// 使用示例
public class Main {public static void main(String[] args) {Day today = Day.MONDAY;System.out.println(today);              // MONDAYSystem.out.println(today.getChinese()); // 星期一System.out.println(today.getNumber());  // 1System.out.println(today.isWeekend());  // false// 遍历枚举System.out.println("一周七天:");for (Day day : Day.values()) {System.out.println(day.getNumber() + ": " + day.getChinese());}// switch语句中使用枚举switch (today) {case MONDAY:System.out.println("今天是周一,要开例会");break;case FRIDAY:System.out.println("周五了,马上周末");break;default:System.out.println("普通工作日");}}
}

3.3 泛型

泛型提供了编译时类型安全检测机制,允许程序员在编译时检测到非法的类型。

// 泛型类
class Box<T> {private T content;public void setContent(T content) {this.content = content;}public T getContent() {return content;}// 泛型方法public <U> void inspect(U u) {System.out.println("T的类型: " + content.getClass().getName());System.out.println("U的类型: " + u.getClass().getName());}
}// 泛型接口
interface Pair<K, V> {K getKey();V getValue();
}// 实现泛型接口
class OrderedPair<K, V> implements Pair<K, V> {private K key;private V value;public OrderedPair(K key, V value) {this.key = key;this.value = value;}@Overridepublic K getKey() {return key;}@Overridepublic V getValue() {return value;}
}// 使用示例
public class Main {public static void main(String[] args) {// 使用泛型类Box<String> stringBox = new Box<>();stringBox.setContent("Hello");System.out.println(stringBox.getContent()); // HellostringBox.inspect(123); // 输出:// T的类型: java.lang.String// U的类型: java.lang.IntegerBox<Integer> integerBox = new Box<>();integerBox.setContent(100);System.out.println(integerBox.getContent()); // 100// 使用泛型接口Pair<String, Integer> pair1 = new OrderedPair<>("年龄", 25);Pair<String, String> pair2 = new OrderedPair<>("姓名", "张三");System.out.println(pair1.getKey() + ": " + pair1.getValue()); // 年龄: 25System.out.println(pair2.getKey() + ": " + pair2.getValue()); // 姓名: 张三// 泛型方法调用printArray(new Integer[]{1, 2, 3});printArray(new String[]{"A", "B", "C"});}// 静态泛型方法public static <E> void printArray(E[] array) {for (E element : array) {System.out.print(element + " ");}System.out.println();}
}

四、面向对象设计原则 (SOLID)

SOLID是五个面向对象设计原则的首字母缩写:

原则名称描述示例
SRP单一职责原则一个类应该只有一个引起变化的原因将用户验证和用户信息管理分开为两个类
OCP开闭原则对扩展开放,对修改关闭使用抽象类和接口,通过继承扩展功能
LSP里氏替换原则子类必须能够替换它们的基类正方形是长方形的子类,但修改边长时需要确保行为一致
ISP接口隔离原则不应该强迫客户端依赖它们不用的接口将大型接口拆分为多个小型专用接口
DIP依赖倒置原则依赖抽象而不是具体实现高层模块通过接口依赖低层模块

4.1 单一职责原则示例

// 违反SRP的类
class BadUser {void login(String username, String password) { /* 登录逻辑 */ }void register(String username, String password, String email) { /* 注册逻辑 */ }void sendEmail(String content) { /* 发送邮件逻辑 */ }void logError(String error) { /* 记录错误日志 */ }
}// 遵循SRP的改进设计
class UserAuthenticator {void login(String username, String password) { /* 登录逻辑 */ }void register(String username, String password, String email) { /* 注册逻辑 */ }
}class EmailService {void sendEmail(String content) { /* 发送邮件逻辑 */ }
}class Logger {void logError(String error) { /* 记录错误日志 */ }
}

4.2 开闭原则示例

// 违反OCP的设计
class ShapeDrawer {void drawShape(Object shape) {if (shape instanceof Circle) {drawCircle((Circle) shape);} else if (shape instanceof Square) {drawSquare((Square) shape);}// 添加新形状需要修改此类}private void drawCircle(Circle circle) { /* 画圆 */ }private void drawSquare(Square square) { /* 画方形 */ }
}// 遵循OCP的改进设计
interface Shape {void draw();
}class Circle implements Shape {@Overridepublic void draw() { /* 画圆 */ }
}class Square implements Shape {@Overridepublic void draw() { /* 画方形 */ }
}class ShapeDrawer {void drawShape(Shape shape) {shape.draw();  // 添加新形状无需修改此类}
}

五、设计模式示例

设计模式是解决特定问题的经验总结,以下是几个常用模式的Java实现。后期会有更详细的文章来分析23种设计模式…

5.1 单例模式

确保一个类只有一个实例,并提供全局访问点。

// 双重检查锁实现单例
class Singleton {// volatile保证可见性和禁止指令重排序private static volatile Singleton instance;// 私有构造方法防止外部实例化private Singleton() {System.out.println("Singleton实例被创建");}public static Singleton getInstance() {if (instance == null) {  // 第一次检查synchronized (Singleton.class) {  // 加锁if (instance == null) {  // 第二次检查instance = new Singleton();}}}return instance;}public void showMessage() {System.out.println("Hello Singleton!");}
}// 使用示例
public class Main {public static void main(String[] args) {// 获取单例实例Singleton singleton = Singleton.getInstance();singleton.showMessage();  // Hello Singleton!// 再次获取,应该是同一个实例Singleton anotherSingleton = Singleton.getInstance();System.out.println(singleton == anotherSingleton);  // true}
}

5.2 工厂模式

定义一个创建对象的接口,但让子类决定实例化哪个类。

// 产品接口
interface Product {void use();
}// 具体产品
class Book implements Product {@Overridepublic void use() {System.out.println("阅读书籍");}
}class Electronic implements Product {@Overridepublic void use() {System.out.println("使用电子产品");}
}// 工厂接口
interface ProductFactory {Product createProduct();
}// 具体工厂
class BookFactory implements ProductFactory {@Overridepublic Product createProduct() {return new Book();}
}class ElectronicFactory implements ProductFactory {@Overridepublic Product createProduct() {return new Electronic();}
}// 使用示例
public class Main {public static void main(String[] args) {ProductFactory factory;Product product;// 创建书籍factory = new BookFactory();product = factory.createProduct();product.use();  // 阅读书籍// 创建电子产品factory = new ElectronicFactory();product = factory.createProduct();product.use();  // 使用电子产品}
}

5.3 观察者模式

定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知。

import java.util.ArrayList;
import java.util.List;// 主题接口
interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}// 观察者接口
interface Observer {void update(float temperature);
}// 具体主题(气象站)
class WeatherStation implements Subject {private List<Observer> observers;private float temperature;public WeatherStation() {observers = new ArrayList<>();}@Overridepublic void registerObserver(Observer o) {observers.add(o);}@Overridepublic void removeObserver(Observer o) {observers.remove(o);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(temperature);}}public void setTemperature(float temperature) {this.temperature = temperature;notifyObservers();}
}// 具体观察者(显示设备)
class DisplayDevice implements Observer {private String name;public DisplayDevice(String name) {this.name = name;}@Overridepublic void update(float temperature) {System.out.println(name + ": 当前温度是 " + temperature + "°C");}
}// 使用示例
public class Main {public static void main(String[] args) {WeatherStation station = new WeatherStation();DisplayDevice phoneDisplay = new DisplayDevice("手机显示屏");DisplayDevice tvDisplay = new DisplayDevice("电视显示屏");// 注册观察者station.registerObserver(phoneDisplay);station.registerObserver(tvDisplay);// 温度变化,通知观察者station.setTemperature(25.5f);// 输出:// 手机显示屏: 当前温度是 25.5°C// 电视显示屏: 当前温度是 25.5°C// 移除一个观察者station.removeObserver(tvDisplay);// 再次温度变化station.setTemperature(26.0f);// 输出:// 手机显示屏: 当前温度是 26.0°C}
}

六、Java 8+ 面向对象新特性

6.1 Lambda表达式

Lambda表达式为Java添加了函数式编程能力。

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;public class Main {public static void main(String[] args) {List<String> languages = Arrays.asList("Java", "Python", "C++", "JavaScript", "Ruby");// 1. 使用匿名内部类languages.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});// 2. 使用Lambda表达式languages.forEach(s -> System.out.println(s));// 3. 使用方法引用languages.forEach(System.out::println);// 带条件的LambdaSystem.out.println("J开头的语言:");filter(languages, s -> s.startsWith("J"));// 多行Lambdalanguages.forEach(s -> {String upper = s.toUpperCase();System.out.println(upper);});}public static void filter(List<String> list, Predicate<String> predicate) {for (String s : list) {if (predicate.test(s)) {System.out.println(s);}}}
}

6.2 Stream API

Stream API提供了一种高效处理集合数据的方式。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;class Product {private String name;private double price;private String category;public Product(String name, double price, String category) {this.name = name;this.price = price;this.category = category;}// getters and toStringpublic String getName() { return name; }public double getPrice() { return price; }public String getCategory() { return category; }@Overridepublic String toString() {return name + "(" + category + "): ¥" + price;}
}public class Main {public static void main(String[] args) {List<Product> products = Arrays.asList(new Product("iPhone", 8999, "手机"),new Product("小米电视", 3999, "家电"),new Product("华为笔记本", 5999, "电脑"),new Product("格力空调", 3299, "家电"),new Product("联想鼠标", 99, "配件"));// 1. 过滤家电类产品System.out.println("家电产品:");products.stream().filter(p -> "家电".equals(p.getCategory())).forEach(System.out::println);// 2. 获取所有产品名称List<String> names = products.stream().map(Product::getName).collect(Collectors.toList());System.out.println("产品名称列表: " + names);// 3. 计算所有产品的总价double total = products.stream().mapToDouble(Product::getPrice).sum();System.out.println("总价: " + total);// 4. 找出最贵的产品products.stream().max((p1, p2) -> Double.compare(p1.getPrice(), p2.getPrice())).ifPresent(p -> System.out.println("最贵的产品: " + p));// 5. 按价格排序System.out.println("按价格排序:");products.stream().sorted((p1, p2) -> Double.compare(p1.getPrice(), p2.getPrice())).forEach(System.out::println);}
}

6.3 接口的默认方法和静态方法

interface Vehicle {// 抽象方法void start();// 默认方法default void stop() {System.out.println("车辆停止");}// 静态方法static void honk() {System.out.println("嘀嘀");}
}interface Alarm {default void stop() {System.out.println("警报停止");}
}class Car implements Vehicle, Alarm {@Overridepublic void start() {System.out.println("汽车启动");}// 必须重写有冲突的默认方法@Overridepublic void stop() {Alarm.super.stop();  // 调用Alarm接口的默认方法Vehicle.super.stop(); // 调用Vehicle接口的默认方法System.out.println("汽车完全停止");}
}public class Main {public static void main(String[] args) {Car car = new Car();car.start();  // 汽车启动car.stop();   // 输出:// 警报停止// 车辆停止// 汽车完全停止Vehicle.honk();  // 嘀嘀 (调用接口静态方法)}
}

七、面向对象编程最佳实践

  1. 遵循命名规范

    • 类名:大驼峰,如 BankAccount
    • 方法名:小驼峰,如 calculateInterest
    • 常量:全大写,下划线分隔,如 MAX_VALUE
  2. 合理使用访问修饰符

    • 优先使用private,只在必要时放宽访问权限
    • 使用protected为子类提供扩展点
  3. 组合优于继承

    • 除非有明显的"is-a"关系,否则优先使用组合
  4. 面向接口编程

    • 依赖抽象而非具体实现,提高灵活性
  5. 避免过度设计

    • 从简单设计开始,随着需求变化逐步演进
  6. 保持类的内聚性

    • 一个类应该只有一个职责
  7. 合理使用设计模式

    • 不要为了模式而模式,只在确实能解决问题时使用
  8. 良好的文档注释

    • 使用Javadoc为公共API添加注释
/*** 银行账户类,提供基本的存款、取款和查询余额功能。*/
public class BankAccount {/*** 账户余额,单位:元*/private double balance;/*** 构造一个新的银行账户* @param initialBalance 初始余额*/public BankAccount(double initialBalance) {this.balance = initialBalance;}/*** 存款操作* @param amount 存款金额,必须大于0* @throws IllegalArgumentException 如果amount不大于0*/public void deposit(double amount) {if (amount <= 0) {throw new IllegalArgumentException("存款金额必须大于0");}balance += amount;}// 其他方法...
}

总结

Java面向对象编程是一个强大而灵活的范式,通过类、对象、继承、多态等概念,我们可以构建出结构良好、易于维护的应用程序。从基础的封装、继承、多态,到高级的设计模式和新特性,Java提供了完整的面向对象支持。

Java 面向对象就是代码界的 “过家家”!类是模板,对象是玩偶,继承像偷师,多态来变装,玩砸了程序当场 “社死”!

“好了,写不动了,再写就要收费了…(暗示白嫖党赶紧收藏)”

在这里插入图片描述

http://www.xdnf.cn/news/2155.html

相关文章:

  • OSPF的不规则区域和特殊区域
  • Spring 声明配置类:@Configuration
  • 基于Python+Neo4j实现新冠信息挖掘系统
  • 力扣面试150题--合并两个有序链表和随机链表的复制
  • BT152-ASEMI机器人率器件专用BT152
  • TEC制冷片详解(STM32)
  • 电机试验平台:实现精准测试与优化设计
  • 【开源飞控】调试
  • 统计定界子数组的数组
  • 下垂控制属于构网型控制技术
  • pytest 技术总结
  • CCF CSP 第30次(2023.05)(4_电力网络_C++)
  • Fedora 43 计划移除所有 GNOME X11 相关软件包
  • Android 13 接入 MediaSession 详细文档
  • 机器学习——朴素贝叶斯法运用
  • 网络攻防第一~四集
  • T型三电平逆变器的SPWM线电压 线与中点电压有几种电平
  • 关闭网桥的STP,解决RHEL10上qemu使用u-boot加载uImage自动加载失败的问题
  • 驱动汽车供应链数字化转型的标杆解决方案:全星研发项目管理APQP软件系统:
  • DP主站转485操作流程
  • vuePress开发和使用
  • WebAssembly全栈革命:在Rust与JavaScript之间构建高性能桥梁
  • 如何轻松将RS232转为Profibus DP,提升PLC效率?
  • ClickHouse查询执行与优化
  • 数据过滤器
  • 阿里云域名智能解析至国内外AWS的合规化部署指南
  • Windows11系统中GIT下载
  • 系统架构设计中的DSSA方法:理论、实践与行业深度应用
  • 【SwitchyOmega安装教程】
  • 【Token系列】01 | Token不是词:GPT如何切分语言的最小单元