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 和一个具体方法 eatDog 类继承了 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 类同时实现了 AnimalMovable 两个接口。每个接口定义了一个方法,Dog 类提供了这些方法的实现。

4. 抽象与接口的比较
特性抽象类接口
关键字abstractinterface
方法实现可以包含抽象方法和具体方法只能包含抽象方法(Java 8+ 支持默认方法和静态方法)
构造方法可以有构造方法没有构造方法
继承关系一个类只能继承一个抽象类一个类可以实现多个接口
成员变量可以有实例变量只能有静态常量(默认是 public static final

二、抽象类类型转换

在 Java 中,抽象类的类型转换通常涉及两种类型的转换:

  1. 父类类型转换为子类(向下转型)。
  2. 子类类型转换为父类(向上转型)。

这两种类型转换背后的核心是 继承关系多态。我们将在下面通过实际的代码示例来进一步说明这两种类型转换。

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 类型的对象。
  • 由于 animalAnimal 类型,所以我们不能直接调用 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 提供了支付的一些通用逻辑,比如生成支付订单、处理支付回调等。
  • 子类 AlipayPaymentProcessorWeChatPaymentProcessor 分别实现具体支付方式的支付流程。
代码实现:
// 定义支付接口
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)则由子类实现。

  • AlipayPaymentProcessorWeChatPaymentProcessor 类分别实现了支付宝和微信支付的具体支付逻辑。

业务场景2:用户通知系统

设计一个通知系统,用户可以选择接收不同类型的通知,如短信、邮件和推送通知。通过接口定义不同通知方式,通过抽象类实现通用的通知发送逻辑。

设计说明:
  • 接口 Notification 定义了通知的发送行为。
  • 抽象类 AbstractNotificationService 提供了发送通知的一些通用方法。
  • 子类 SMSNotificationServiceEmailNotificationServicePushNotificationService 实现了具体的通知发送方式。
代码实现:
// 定义通知接口
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 方法在子类中实现。
  • SMSNotificationServiceEmailNotificationServicePushNotificationService 分别实现了发送不同类型通知的逻辑。
业务场景3:订单管理系统

设计一个订单管理系统,其中有多种订单类型(如普通订单和促销订单),它们共享一些通用的订单处理逻辑,但也有不同的处理方式。我们使用抽象类来实现通用订单处理逻辑,接口来定义每种订单类型的额外操作。

设计说明:
  • 接口 OrderType 定义了不同订单类型的行为。
  • 抽象类 Order 提供了订单的基本属性和通用操作。
  • 子类 NormalOrderPromotionalOrder 分别实现普通订单和促销订单的处理逻辑。
代码实现:
// 定义订单类型接口
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 和金额等字段,以及通用的订单处理方法。
  • NormalOrderPromotionalOrder 类分别处理普通订单和促销订单的折扣计算,并在 processOrder 方法中执行具体的折扣应用。
总结:

我们通过抽象类和接口的结合来实现业务逻辑的高内聚和低耦合。抽象类提供了通用的功能实现,而接口则定义了各类支付方式、通知方式和订单类型的特定行为。这样设计不仅提高了代码的可扩展性,还增强了系统的灵活性,使得新功能的添加变得简单。

四、练习题目

1、选择题
  1. 以下哪个选项是正确的,关于Java中的接口?

    • A. 一个类可以实现多个接口
    • B. 一个类只能实现一个接口
    • C. 接口不能有任何方法
    • D. 接口中的方法只能是静态方法

    正确答案:A

  2. 下列关于抽象类的描述,哪个是正确的?

    • A. 抽象类不能有构造方法
    • B. 抽象类可以有实现的方法和抽象方法
    • C. 抽象类不能有成员变量
    • D. 抽象类必须定义一个抽象方法

    正确答案:B

  3. 接口与抽象类的区别是什么?

    • A. 接口不能有成员变量,而抽象类可以
    • B. 接口不能包含任何方法实现,而抽象类可以
    • C. 接口不可以继承其他接口,而抽象类可以
    • D. 抽象类和接口没有任何区别

    正确答案:A

  4. 下面的代码是如何工作?

    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

  5. 如果一个类继承了抽象类,并且没有实现所有抽象方法,那么这个类必须是:

    • A. 抽象类
    • B. 接口
    • C. 具体类
    • D. 编译错误

    正确答案:A


2、代码检查题
  1. 检查以下代码并找出错误:

    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();
    
  2. 检查以下代码并找出错误:

    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");
    }
    
  3. 检查以下代码并找出错误:

    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、代码设计题
  1. 设计一个抽象类Employee,该类包含namesalary属性,并有一个抽象方法calculateBonus(),然后实现两个子类ManagerDeveloper。其中,Manager类根据固定比例计算奖金,Developer类根据工作年限计算奖金。

    提示:

    • Employee类包含namesalary
    • 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;}
    }
    
  2. 设计一个接口Flyable,该接口包含fly()方法。创建类BirdPlane分别实现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");}
    }
    
  3. 设计一个接口Playable,并实现FootballPlayerBasketballPlayer类。每个类都有一个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");}
    }
    
  4. 设计一个抽象类Appliance,包含turnOn()turnOff()方法。创建WashingMachineRefrigerator两个子类,并实现这些方法。

    提示:

    • WashingMachineturnOn()方法打印“Washing machine is running”。
    • RefrigeratorturnOn()方法打印“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");}
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/15452.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字电路-基础逻辑门实验

基础逻辑门是数字电路设计的核心元件,它们执行的是基本的逻辑运算。通过这些基本运算,可以构建出更为复杂的逻辑功能。常见的基础逻辑门包括与门(AND)、或门(OR)、非门(NOT)、异或门…

哪吒闹海!SCI算法+分解组合+四模型原创对比首发!SGMD-FATA-Transformer-LSTM多变量时序预测

哪吒闹海!SCI算法分解组合四模型原创对比首发!SGMD-FATA-Transformer-LSTM多变量时序预测 目录 哪吒闹海!SCI算法分解组合四模型原创对比首发!SGMD-FATA-Transformer-LSTM多变量时序预测效果一览基本介绍程序设计参考资料 效果一览…

C++,STL 迭代器简介:概念、分类、操作

文章目录 引言一、迭代器的基本概念1.1 什么是迭代器?1.2 迭代器的意义二、迭代器的分类2.1 示意图:迭代器能力层级2.2 示例:不同迭代器的操作三、迭代器的常用操作3.1 基本操作3.2 随机访问迭代器专用操作示例代码:随机访问迭代器四、迭代器的通用用法4.1 遍历容器4.2 配合…

EasyExcel 导出合并层级单元格

EasyExcel 导出合并层级单元格 一、案例 案例一 1.相同订单号单元格进行合并 合并结果 案例二 1.相同订单号的单元格进行合并2.相同订单号的总数和总金额进行合并 合并结果 案例三 1.相同订单号的单元格进行合并2.相同订单号的商品分类进行合并3.相同订单号的总数和总金额…

常用的python库-安装与使用

常用的python库函数 yield关键字openslide库openslide对象的常用属性 cv2库numpy库ASAP库-multiresolutionimageinterface库ASAP库的安装ASAP库的使用 concurrent.futures.ThreadPoolExecutorxml.etree.ElementTree库skimage库PIL.Image库 PIL.Image.Imagedetectron2库数据增强…

C++基础系列【8】如何解决编译器报的错误

博主介绍:程序喵大人 35- 资深C/C/Rust/Android/iOS客户端开发10年大厂工作经验嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手《C20高级编程》《C23高级编程》等多本书籍著译者更多原创精品文章,首发gzh,见文末👇&#x1f…

程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<8>

大家好啊,我是小象٩(๑ω๑)۶ 我的博客:Xiao Xiangζั͡ޓއއ 很高兴见到大家,希望能够和大家一起交流学习,共同进步。 今天我们复习前面学习的指针知识 目录 关于指针数组和数组指针的区别指针数组(Array of Poi…

UE5.5 PCGFrameWork--GPU CustomHLSL

在上一篇UE5.5 PCGFrameWork使用入门-CSDN博客 大致介绍了UE5 PCG框架的基本使用. 本篇探索PCGFrame的高级应用--GPU点云。也就是利用GPU HLSL编程对点云进行操纵,可以大幅度提升点云生成效率。 目前在UE5 PCG框架中,点云GPU的应用大致分为三类: Point…

Games202 Lecture11 LTC | Disney principled BRDF | NPR

Shading with microfacet BRDFs under polygonal lighting -Linearly Transformed Cosines(LTC)Real-Time PBR Materials cont. -Disney principled BRDFNon-photorealistic rendering(NPR) Linearly Transformed Cosines(LTC) lobe花瓣 BRDF的2d形状 基本思路: 任意BRDF变…

Flink 内存模型各部分大小计算公式

Flink 的运行平台 如果 Flink 是运行在 yarn 或者 standalone 模式的话,其实都是运行在 JVM 的基础上的,所以首先 Flink 组件运行所需要给 JVM 本身要耗费的内存大小。无论是 JobManager 或者 TaskManager ,他们 JVM 内存的大小都是一样的&a…

学习数据结构(8)双向链表

1.双向链表的实现 双向链表一般指带头双向循环链表 (1)双向链表的声明 (2)双向链表的打印 (3)向内存申请节点 (4)初始化双向链表 或 (5)尾部插入 &#xf…

【漫话机器学习系列】088.常见的输出层激活函数(Common Output Layer Activation Functions)

在神经网络中,输出层(Output Layer) 的激活函数(Activation Function)直接决定了模型的输出形式,并影响损失函数的选择及训练效果。不同的任务类型(如分类或回归)需要使用不同的激活…

Python 鼠标轨迹 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序,它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言,原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势: 模拟…

工业相机在工业生产制造过程中的视觉检测技术应用

随着技术不断发展以及工业4.0时代的到来,利用工业相机进行视觉检测技术已经成为制造业不可或缺的一部分。通过结合先进的计算机视觉、AI算法和自动化设备,工业视觉检测为生产线质量控制和效率提升提供了革命性的解决方案。 一、什么是工业视觉检测技术 …

了解网络层

目录 一、IP协议 二、地址管理 IP地址 概念 作用 格式 网段划分 三、路由选择 网络层要做的事情主要是两个方面: 地址管理:制定一系列的规则,通过地址,描述出网络上一个设备的位置。路由选择:网络环境比较复杂…

NO.11十六届蓝桥杯备战|if-else语句|嵌套if|悬空else|练习4道(C++)

if-else语句 if语句 if语句的语法形式如下: if ( 表达式 ) 语句;表达式成⽴(为真),则语句执⾏,表达式不成⽴(为假),则语句不执⾏ 0为假,⾮0表⽰真,也就是…

Json-RPC框架项目(一)

目录 1. 项目介绍: 2. 技术选择; 3. 第三方库介绍; 4. 项目功能; 5. 模块功能; 6. 项目实现: 1. 项目介绍: RPC是远程过程调用, 像调用本地接口一样调用远程接口, 进行完成业务处理, 计算任务等, 一个完整的RPC包括: 序列化协议, 通信协议, 连接复用, 服务注册, 服务发…

Discourse 创建和配置用户自定义字段

用户自定义字段能够让你在用户注册的是要求用户提供更多的信息。这些用户提供的信息可以在用户名片,用户摘要页面下显示,甚至还可以通过 Data Explorer plugin 插件进行查询。 本文能够帮助你对这些字段进行配置和设置。 添加一个用户字段 进入 Admin…

从零到一:我的元宵灯谜小程序诞生记

缘起:一碗汤圆引发的灵感 去年元宵节,我正捧着热腾腾的汤圆刷朋友圈,满屏都是"转发锦鲤求灯谜答案"的动态。看着大家对着手机手忙脚乱地切换浏览器查答案,我突然拍案而起:为什么不做一个能即时猜灯谜的微信…

【C++11】lambda和包装器

1.新的类功能 1.1默认的移动构造和移动赋值 原来C类中,有6个默认成员函数:构造函数/析构函数/拷⻉构造函数/拷⻉赋值重载/取地址重 载/const 取地址重载,最后重要的是前4个,后两个⽤处不⼤,默认成员函数就是我们不写…