JAVA中的抽象学习
一、Java SE 中的抽象概念
在 Java 中,抽象(Abstraction)是面向对象编程的重要特性之一。抽象的核心思想是“只关注重要的特性,而忽略不重要的细节”。抽象通常通过抽象类和接口来实现,它帮助开发者将复杂的系统隐藏在简单的接口和设计背后。
1. 抽象的定义
抽象的目的是从一组具体事物中提取出通用的特性,而忽略它们的具体实现细节。在 Java 中,抽象可以通过以下两种方式来实现:
- 抽象类(Abstract Class):用来表示一些基本特性,但不能直接实例化。它可以包含抽象方法(没有实现的方法)和具体方法(有实现的方法)。
- 接口(Interface):定义一组方法签名,不提供方法实现。实现接口的类需要提供接口中所有方法的实现。
2. 抽象类(Abstract Class)
抽象类是一个包含抽象方法的类,抽象方法是没有方法体的方法。抽象类可以包含具体的方法(已实现的方法)和成员变量。
抽象类的特点:
- 可以包含抽象方法和具体方法。
- 不可以直接实例化(无法创建抽象类的对象)。
- 可以有构造方法和成员变量。
抽象类的例子:
abstract class Animal {// 抽象方法,没有实现public abstract void sound();// 具体方法,有实现public void eat() {System.out.println("This animal eats food.");}
}class Dog extends Animal {// 提供抽象方法的实现public void sound() {System.out.println("Woof Woof");}
}class Main {public static void main(String[] args) {Animal dog = new Dog();dog.sound(); // 输出: Woof Woofdog.eat(); // 输出: This animal eats food.}
}
在这个例子中,Animal 是一个抽象类,它定义了一个抽象方法 sound 和一个具体方法 eat。Dog 类继承了 Animal 类并实现了 sound 方法。
3. 接口(Interface)
接口是一个完全抽象的类,它定义了方法的签名(没有实现),任何类都可以实现一个接口,并提供接口中方法的实现。
接口的特点:
- 只能包含抽象方法(从 Java 8 开始,接口可以包含默认方法和静态方法)。
- 类通过
implements关键字实现接口。 - 一个类可以实现多个接口。
接口的例子:
interface Animal {// 接口中的方法没有实现void sound();
}interface Movable {void move();
}class Dog implements Animal, Movable {public void sound() {System.out.println("Woof Woof");}public void move() {System.out.println("The dog runs.");}
}class Main {public static void main(String[] args) {Dog dog = new Dog();dog.sound(); // 输出: Woof Woofdog.move(); // 输出: The dog runs.}
}
在这个例子中,Dog 类同时实现了 Animal 和 Movable 两个接口。每个接口定义了一个方法,Dog 类提供了这些方法的实现。
4. 抽象与接口的比较
| 特性 | 抽象类 | 接口 |
|---|---|---|
| 关键字 | abstract | interface |
| 方法实现 | 可以包含抽象方法和具体方法 | 只能包含抽象方法(Java 8+ 支持默认方法和静态方法) |
| 构造方法 | 可以有构造方法 | 没有构造方法 |
| 继承关系 | 一个类只能继承一个抽象类 | 一个类可以实现多个接口 |
| 成员变量 | 可以有实例变量 | 只能有静态常量(默认是 public static final) |
二、抽象类类型转换
在 Java 中,抽象类的类型转换通常涉及两种类型的转换:
- 父类类型转换为子类(向下转型)。
- 子类类型转换为父类(向上转型)。
这两种类型转换背后的核心是 继承关系 和 多态。我们将在下面通过实际的代码示例来进一步说明这两种类型转换。
1. 父类转子类(向下转型)
向下转型是指将父类对象转化为子类对象。在实际开发中,这种转换通常是在调用子类特有的方法时使用。前提条件是,父类对象的实际类型是子类类型(即父类引用指向了一个子类实例),否则会抛出 ClassCastException 异常。
例子:父类转子类(向下转型)
abstract class Animal {public abstract void sound();
}class Dog extends Animal {public void sound() {System.out.println("Woof Woof");}public void fetch() {System.out.println("Dog is fetching the ball!");}
}class Main {public static void main(String[] args) {Animal animal = new Dog(); // 父类引用指向子类对象// 向下转型:将父类引用转换为子类引用Dog dog = (Dog) animal; // 强制转换为 Dog 类型dog.sound(); // 输出: Woof Woofdog.fetch(); // 输出: Dog is fetching the ball!}
}
解释:
- 在这个例子中,
Animal是一个抽象类,Dog是它的子类。 - 我们创建了一个
Animal类型的引用animal,它指向了一个Dog类型的对象。 - 由于
animal是Animal类型,所以我们不能直接调用Dog类中定义的fetch方法。 - 为了调用
Dog特有的方法,我们需要将Animal类型的引用向下转型成Dog类型。这样就能访问Dog类特有的方法fetch()。 - 转型时,
animal实际上指向的是一个Dog对象,所以可以安全地进行向下转型。
如果将 animal 指向一个非 Dog 类型的对象(比如 Cat),在进行向下转型时就会抛出 ClassCastException。
2. 子类转父类(向上转型)
向上转型是指将子类对象转化为父类对象。由于子类是父类的一种特殊类型,向上转型是安全的,不需要显式强制转换。这种转换常见于多态的实现,它允许子类的对象被当做父类对象来处理。
例子:子类转父类(向上转型)
abstract class Animal {public abstract void sound();
}class Dog extends Animal {public void sound() {System.out.println("Woof Woof");}public void fetch() {System.out.println("Dog is fetching the ball!");}
}class Main {public static void main(String[] args) {Dog dog = new Dog(); // 创建 Dog 类型对象Animal animal = dog; // 向上转型:Dog 转换为 Animal 类型animal.sound(); // 输出: Woof Woof// animal.fetch(); // 编译错误:Animal 类型没有 fetch 方法}
}
解释:
- 在这个例子中,
Dog类是Animal类的子类。我们创建了一个Dog类型的对象dog,然后将其赋值给Animal类型的变量animal。 - 这里的转换是 向上转型,因为
Dog类型的对象被赋值给了Animal类型的引用,Java 自动进行这种转换。 - 向上转型后,
animal变量只能访问父类Animal中定义的方法。如果调用animal.fetch(),编译器会报错,因为fetch()是Dog类的特有方法,Animal类中没有定义fetch()方法。 - 然而,由于
animal实际上是指向Dog对象,所以可以调用sound()方法,并且会输出Dog类的实现。
3. 父类转子类的异常情况
如果父类引用的实际类型并非子类类型,进行类型转换时会抛出 ClassCastException。
例子:类型转换异常
abstract class Animal {public abstract void sound();
}class Dog extends Animal {public void sound() {System.out.println("Woof Woof");}
}class Cat extends Animal {public void sound() {System.out.println("Meow");}
}class Main {public static void main(String[] args) {Animal animal = new Cat(); // 创建 Cat 类型的对象,引用类型为 Animal// 错误的类型转换:将 Cat 转换为 DogDog dog = (Dog) animal; // 会抛出 ClassCastException 异常dog.sound(); // 不会执行到这里}
}
解释:
- 在这个例子中,
animal实际上指向一个Cat对象,但是我们尝试将它转换为Dog类型。这会导致ClassCastException异常。 - 由于
animal的实际类型是Cat,而不是Dog,Java 会抛出ClassCastException。
总结
- 父类转子类(向下转型):需要使用强制类型转换,但必须确保父类对象的实际类型是子类类型,否则会抛出
ClassCastException异常。 - 子类转父类(向上转型):是安全的,Java 会自动进行类型转换,子类对象可以赋值给父类类型的引用,但只能访问父类中定义的方法和属性。
三、抽象类和接口的案例说明
业务场景1:支付系统设计
我们将设计一个支付系统,其中有多种支付方式,比如 支付宝 和 微信支付。每种支付方式都需要实现相同的支付接口,而支付系统的核心逻辑通过一个抽象类来实现。
设计说明:
- 接口
PaymentMethod定义了支付的基本操作,如pay。 - 抽象类
PaymentProcessor提供了支付的一些通用逻辑,比如生成支付订单、处理支付回调等。 - 子类
AlipayPaymentProcessor和WeChatPaymentProcessor分别实现具体支付方式的支付流程。
代码实现:
// 定义支付接口
interface PaymentMethod {void pay(double amount); // 支付方法
}// 抽象支付处理类
abstract class PaymentProcessor {protected String orderId;public PaymentProcessor(String orderId) {this.orderId = orderId;}// 公共的支付处理逻辑public void processPayment(double amount) {System.out.println("Processing payment for order: " + orderId);initiatePayment(amount);onPaymentCompleted();}// 每个支付方式的具体支付操作由子类实现protected abstract void initiatePayment(double amount);// 支付完成后的操作protected void onPaymentCompleted() {System.out.println("Payment for order " + orderId + " completed.");}
}// 实现支付宝支付
class AlipayPaymentProcessor extends PaymentProcessor implements PaymentMethod {public AlipayPaymentProcessor(String orderId) {super(orderId);}@Overrideprotected void initiatePayment(double amount) {System.out.println("Initiating Alipay payment of amount: " + amount);}@Overridepublic void pay(double amount) {processPayment(amount);}
}// 实现微信支付
class WeChatPaymentProcessor extends PaymentProcessor implements PaymentMethod {public WeChatPaymentProcessor(String orderId) {super(orderId);}@Overrideprotected void initiatePayment(double amount) {System.out.println("Initiating WeChat payment of amount: " + amount);}@Overridepublic void pay(double amount) {processPayment(amount);}
}public class Main {public static void main(String[] args) {PaymentProcessor alipayProcessor = new AlipayPaymentProcessor("AL123456");alipayProcessor.pay(100.0);PaymentProcessor weChatProcessor = new WeChatPaymentProcessor("WX123456");weChatProcessor.pay(200.0);}
}
设计说明:
-
PaymentMethod接口定义了支付行为。 -
PaymentProcessor抽象类提供了支付流程的通用处理(如processPayment方法),而具体的支付操作(如initiatePayment)则由子类实现。 -
AlipayPaymentProcessor和WeChatPaymentProcessor类分别实现了支付宝和微信支付的具体支付逻辑。
业务场景2:用户通知系统
设计一个通知系统,用户可以选择接收不同类型的通知,如短信、邮件和推送通知。通过接口定义不同通知方式,通过抽象类实现通用的通知发送逻辑。
设计说明:
- 接口
Notification定义了通知的发送行为。 - 抽象类
AbstractNotificationService提供了发送通知的一些通用方法。 - 子类
SMSNotificationService、EmailNotificationService、PushNotificationService实现了具体的通知发送方式。
代码实现:
// 定义通知接口
interface Notification {void sendNotification(String message);
}// 抽象通知服务类
abstract class AbstractNotificationService implements Notification {protected String userId;public AbstractNotificationService(String userId) {this.userId = userId;}// 发送通知的通用逻辑public void sendNotification(String message) {System.out.println("Sending notification to user: " + userId);sendSpecificNotification(message);}// 每个通知方式的具体发送操作由子类实现protected abstract void sendSpecificNotification(String message);
}// 短信通知服务
class SMSNotificationService extends AbstractNotificationService {public SMSNotificationService(String userId) {super(userId);}@Overrideprotected void sendSpecificNotification(String message) {System.out.println("Sending SMS: " + message);}
}// 邮件通知服务
class EmailNotificationService extends AbstractNotificationService {public EmailNotificationService(String userId) {super(userId);}@Overrideprotected void sendSpecificNotification(String message) {System.out.println("Sending Email: " + message);}}// 推送通知服务
class PushNotificationService extends AbstractNotificationService {public PushNotificationService(String userId) {super(userId);}@Overrideprotected void sendSpecificNotification(String message) {System.out.println("Sending Push Notification: " + message);}
}public class Main {public static void main(String[] args) {Notification smsService = new SMSNotificationService("User123");smsService.sendNotification("Your order has been shipped!");Notification emailService = new EmailNotificationService("User123");emailService.sendNotification("Your invoice is ready!");Notification pushService = new PushNotificationService("User123");pushService.sendNotification("You have a new message!");}
}
设计说明:
Notification接口定义了sendNotification方法,用于发送通知。AbstractNotificationService提供了发送通知的通用流程,包括处理用户ID等,而具体的通知发送方式由sendSpecificNotification方法在子类中实现。SMSNotificationService、EmailNotificationService和PushNotificationService分别实现了发送不同类型通知的逻辑。
业务场景3:订单管理系统
设计一个订单管理系统,其中有多种订单类型(如普通订单和促销订单),它们共享一些通用的订单处理逻辑,但也有不同的处理方式。我们使用抽象类来实现通用订单处理逻辑,接口来定义每种订单类型的额外操作。
设计说明:
- 接口
OrderType定义了不同订单类型的行为。 - 抽象类
Order提供了订单的基本属性和通用操作。 - 子类
NormalOrder和PromotionalOrder分别实现普通订单和促销订单的处理逻辑。
代码实现:
// 定义订单类型接口
interface OrderType {void applyDiscount(); // 订单折扣
}// 抽象订单类
abstract class Order {protected String orderId;protected double amount;public Order(String orderId, double amount) {this.orderId = orderId;this.amount = amount;}// 处理订单public void processOrder() {System.out.println("Processing order: " + orderId);applyDiscount();printReceipt();}// 每个订单的折扣操作由子类实现protected abstract void applyDiscount();// 打印订单收据protected void printReceipt() {System.out.println("Order " + orderId + " with amount: " + amount);}
}// 普通订单
class NormalOrder extends Order implements OrderType {public NormalOrder(String orderId, double amount) {super(orderId, amount);}@Overrideprotected void applyDiscount() {System.out.println("Applying no discount for normal order.");}
}// 促销订单
class PromotionalOrder extends Order implements OrderType {public PromotionalOrder(String orderId, double amount) {super(orderId, amount);}@Overrideprotected void applyDiscount() {System.out.println("Applying 20% discount for promotional order.");amount = amount * 0.8; // 20% 折扣}}public class Main {public static void main(String[] args) {Order normalOrder = new NormalOrder("ORD12345", 500.0);normalOrder.processOrder();Order promoOrder = new PromotionalOrder("ORD54321", 500.0);promoOrder.processOrder();}
}
设计说明:
OrderType接口定义了应用折扣的行为。Order抽象类提供了订单的基础逻辑,包含订单的 ID 和金额等字段,以及通用的订单处理方法。NormalOrder和PromotionalOrder类分别处理普通订单和促销订单的折扣计算,并在processOrder方法中执行具体的折扣应用。
总结:
我们通过抽象类和接口的结合来实现业务逻辑的高内聚和低耦合。抽象类提供了通用的功能实现,而接口则定义了各类支付方式、通知方式和订单类型的特定行为。这样设计不仅提高了代码的可扩展性,还增强了系统的灵活性,使得新功能的添加变得简单。
四、练习题目
1、选择题
-
以下哪个选项是正确的,关于Java中的接口?
- A. 一个类可以实现多个接口
- B. 一个类只能实现一个接口
- C. 接口不能有任何方法
- D. 接口中的方法只能是静态方法
正确答案:A
-
下列关于抽象类的描述,哪个是正确的?
- A. 抽象类不能有构造方法
- B. 抽象类可以有实现的方法和抽象方法
- C. 抽象类不能有成员变量
- D. 抽象类必须定义一个抽象方法
正确答案:B
-
接口与抽象类的区别是什么?
- A. 接口不能有成员变量,而抽象类可以
- B. 接口不能包含任何方法实现,而抽象类可以
- C. 接口不可以继承其他接口,而抽象类可以
- D. 抽象类和接口没有任何区别
正确答案:A
-
下面的代码是如何工作?
interface Animal {void sound(); }class Dog implements Animal {public void sound() {System.out.println("Bark");} }public class Test {public static void main(String[] args) {Animal myAnimal = new Dog();myAnimal.sound();} }- A. 会打印“Meow”
- B. 会打印“Bark”
- C. 编译错误,因为接口没有实现
- D. 编译错误,因为类Dog没有提供sound方法实现
正确答案:B
-
如果一个类继承了抽象类,并且没有实现所有抽象方法,那么这个类必须是:
- A. 抽象类
- B. 接口
- C. 具体类
- D. 编译错误
正确答案:A
2、代码检查题
-
检查以下代码并找出错误:
abstract class Shape {abstract void draw(); }class Circle extends Shape {void draw() {System.out.println("Drawing Circle");} }class Test {public static void main(String[] args) {Shape s = new Shape(); // 错误s.draw();} }问题: 代码中存在一个错误,
Shape是抽象类,不能直接实例化,应该实例化Circle类。修复:
Shape s = new Circle(); // 正确 s.draw(); -
检查以下代码并找出错误:
interface Animal {void eat();void sleep(); }class Dog implements Animal {void eat() {System.out.println("Dog eating");}void sleep() {System.out.println("Dog sleeping");} }问题:
Dog类中没有正确实现Animal接口中的方法,方法声明缺少public修饰符。修复:
public void eat() {System.out.println("Dog eating"); }public void sleep() {System.out.println("Dog sleeping"); } -
检查以下代码并找出错误:
abstract class Vehicle {abstract void move(); }class Car extends Vehicle {void move() {System.out.println("Car moving");} }public class Test {public static void main(String[] args) {Vehicle v = new Car();v.move();} }问题: 代码没有问题。
Car类正确地继承了Vehicle并实现了move方法,程序会正常运行并输出“Car moving”。修复: 不需要修复,代码是正确的。
3、代码设计题
-
设计一个抽象类
Employee,该类包含name、salary属性,并有一个抽象方法calculateBonus(),然后实现两个子类Manager和Developer。其中,Manager类根据固定比例计算奖金,Developer类根据工作年限计算奖金。提示:
Employee类包含name和salary。Manager类奖金为salary * 0.1。Developer类奖金为yearsOfExperience * 500。
代码示例:
abstract class Employee {String name;double salary;Employee(String name, double salary) {this.name = name;this.salary = salary;}abstract double calculateBonus(); }class Manager extends Employee {Manager(String name, double salary) {super(name, salary);}double calculateBonus() {return salary * 0.1;} }class Developer extends Employee {int yearsOfExperience;Developer(String name, double salary, int yearsOfExperience) {super(name, salary);this.yearsOfExperience = yearsOfExperience;}double calculateBonus() {return yearsOfExperience * 500;} } -
设计一个接口
Flyable,该接口包含fly()方法。创建类Bird和Plane分别实现Flyable接口,并在fly()方法中输出不同的飞行信息。提示:
Bird类输出“Bird is flying”。Plane类输出“Plane is flying”。
代码示例:
interface Flyable {void fly(); }class Bird implements Flyable {public void fly() {System.out.println("Bird is flying");} }class Plane implements Flyable {public void fly() {System.out.println("Plane is flying");} } -
设计一个接口
Playable,并实现FootballPlayer和BasketballPlayer类。每个类都有一个play()方法,分别打印“Playing football”和“Playing basketball”。提示:
FootballPlayer类和BasketballPlayer类都实现Playable接口。
代码示例:
interface Playable {void play(); }class FootballPlayer implements Playable {public void play() {System.out.println("Playing football");} }class BasketballPlayer implements Playable {public void play() {System.out.println("Playing basketball");} } -
设计一个抽象类
Appliance,包含turnOn()和turnOff()方法。创建WashingMachine和Refrigerator两个子类,并实现这些方法。提示:
WashingMachine的turnOn()方法打印“Washing machine is running”。Refrigerator的turnOn()方法打印“Refrigerator is cooling”。
代码示例:
abstract class Appliance {abstract void turnOn();abstract void turnOff(); }class WashingMachine extends Appliance {void turnOn() {System.out.println("Washing machine is running");}void turnOff() {System.out.println("Washing machine is off");} }class Refrigerator extends Appliance {void turnOn() {System.out.println("Refrigerator is cooling");}void turnOff() {System.out.println("Refrigerator is off");} }
相关文章:
JAVA中的抽象学习
一、Java SE 中的抽象概念 在 Java 中,抽象(Abstraction)是面向对象编程的重要特性之一。抽象的核心思想是“只关注重要的特性,而忽略不重要的细节”。抽象通常通过抽象类和接口来实现,它帮助开发者将复杂的系统隐藏在…...
在 Go 中实现事件溯源:构建高效且可扩展的系统
事件溯源(Event Sourcing)是一种强大的架构模式,它通过记录系统状态的变化(事件)来重建系统的历史状态。这种模式特别适合需要高可扩展性、可追溯性和解耦的系统。在 Go 语言中,事件溯源可以通过一些简单的…...
加解密 | AES加、解密学习
加解密 | AES加、解密学习 你的代码实现了一个简单的AES(高级加密标准)加密和解密的测试程序。以下是对代码的分析和一些改进建议: 代码功能 初始化数据和密钥: 定义了一个16字节的输入数据 input_data。定义了一个16字节的AES…...
【学术投稿-2025年计算机视觉研究进展与应用国际学术会议 (ACVRA 2025)】CSS样式解析:行内、内部与外部样式的区别与优先级分析
简介 2025年计算机视觉研究进展与应用(ACVRA 2025)将于2025年2月28-3月2日在中国广州召开,会议将汇聚世界各地的顶尖学者、研究人员和行业专家,聚焦计算机视觉领域的最新研究动态与应用成就。本次会议将探讨前沿技术,…...
MongoDB 基本操作
一、数据库操作 1. 切换或创建数据库 使用use命令切换到指定数据库,若该数据库不存在,在首次插入数据时会自动创建。 use myDatabase 2. 查看所有数据库 使用show dbs命令查看 MongoDB 实例中的所有数据库。 show dbs 3. 删除当前数据库 使用db.…...
Eclipse JSP/Servlet 深入解析
Eclipse JSP/Servlet 深入解析 引言 随着互联网的快速发展,Java Web开发技术逐渐成为企业级应用开发的主流。在Java Web开发中,JSP(JavaServer Pages)和Servlet是两个核心组件,它们共同构成了Java Web应用程序的基础。本文将深入解析Eclipse平台下的JSP/Servlet技术,帮…...
Hyperledger caliper 性能测试
前言:Hyperledger caliper 的本质是使用node对被测试网络进行压力测试,因此需要nodejs。本次使用 Hyperledger caliper 0.5 对 fabric 1.4.6进行压测 准备条件:nodejs 16 (略 linux下 解压环境变量即可) # 创建工作…...
Record-Mode 备案免关站插件,让 WordPress 备案不影响 SEO 和收录
专为 WordPress 网站设计的实用工具,旨在帮助网站在备案期间无需关闭即可正常收录所有页面的信息,利于SEO。 功能特性 免关站展示:开启插件后,非管理员用户访问网站时,会看到以半透明遮罩层或不透明全屏遮罩样式呈现的…...
【Java 面试 八股文】Redis篇
Redis 1. 什么是缓存穿透?怎么解决?2. 你能介绍一下布隆过滤器吗?3. 什么是缓存击穿?怎么解决?4. 什么是缓存雪崩?怎么解决?5. redis做为缓存,mysql的数据如何与redis进行同步呢&…...
介绍几款免费的显示器辅助工具!
今天为大家介绍几款实用的显示器辅助软件,它们可以帮助你轻松切换显示源调节、显示器亮度,甚至优化显示效果,让你的屏幕使用体验更加便捷和舒适。 Monitor Brightness Adjuster-多屏幕亮度调节工具 如果你需要同时使用多个显示器࿰…...
django配置跨域
1、第一种 from django.views.decorators.csrf import csrf_exemptcsrf_exempt第二种 安装 pip install django-cors-headers在配置文件settings.py进入 INSTALLED_APPS [..."corsheaders", # 添加 ]MIDDLEWARE [corsheaders.middleware.CorsMiddleware, # 添加…...
web前端第三次作业
题目 本期作业 WEB第三次作业 请使用JS实一个网页中登录窗口的显示/隐藏,页面中拖动移动,并且添加了边界判断的网页效 代码图片 效果展示 代码 <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8&qu…...
【Pandas】pandas Series align
Pandas2.2 Series Computations descriptive stats 方法描述Series.align(other[, join, axis, level, …])用于将两个 Series 对齐,使其具有相同的索引 pandas.Series.align pandas.Series.align() 方法用于将两个 Series 对齐,使其具有相同的索引。…...
DeepSeek-V3网络模型架构图解
DeepSeek-V3网络架构的创新主要在两次,分别是在前馈层的MOE(混合专家模型)和在注意力中的MHA(多头潜在注意力,一种注意力计算规模压缩技术)。 MOE(混合专家模型) 回顾最初的MOE GS…...
Linux系统管理小课堂
1. 文件系统:你的数字房间大扫除 例子1:藏日记本的保险箱 chmod 700 my_diary.txt 👻 解释:把日记文件权限改成「只有主人能读写」,室友偷看时系统会翻白眼:“Permission denied!” 例子2&…...
明远智睿核心板在智能家居与工业网关中的应用实践
**——从硬件支持到场景落地的技术路径** SSD2351 在智能家居与工业物联网领域,设备需具备实时响应、多协议兼容及边缘计算能力。明远智睿新款核心板凭借其硬件特性,可高效支撑以下典型场景: #### **场景一:智能家居中枢网关**…...
Windows 系统 GDAL库 配置到 Qt 上
在地理信息开发中广泛使用的开源库,GDAL(Geospatial Data Abstraction Library))库提供了读取和处理各种地理空间数据格式的能力。 准备阶段 下载 GDAL 库:前往 GDAL 的官方网站(https://www.gisinternals.com/)下载…...
部署onlyoffice后,php版的callback及小魔改(logo和关于)
作为这篇博文的补充CentOS9 安装Docker+Dpanel+onlyoffice(https、更改字体、字号、去除限制)的避坑笔记,现在继续… 本次主要内容有:php中callback的调用、自签证书调用callback遇到SSL certificate problem: unable to get local issuer certificate问题、修改onlyoffic…...
《qt open3d网格拉普拉斯平滑》
qt open3d网格拉普拉斯平滑 效果展示二、流程三、代码效果展示 二、流程 创建动作,链接到槽函数,并把动作放置菜单栏 参照前文 三、代码 1、槽函数实现 void on_actionFilterLaplacian_triggered();void MainWindow::on_actionFil...
【愚公系列】《Python网络爬虫从入门到精通》004-请求模块urllib3
标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主&…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
