Java 基础学习(八)多态、接口、造型与内部类

news2024/7/4 6:16:32

1 多态

1.1 多态

1.1.1 多态的意义

一个类型的引用在指向不同的对象时会有不同的实现。依然借助前面案例中的 Person类、Student类和 Teacher 类举例,看如下的代码:

Person p1 = new Student();
Person p2 = new Teacher();
p1.schedule();
p2.schedule();

同样声明为 Person 类型的变量 p1和p2,当指向不同的对象时,可以有不同的表现。这种现象在 Java中被称为多态。

多态是面向对象的三大基本特征之一,包含:

  • 个体多态
  • 行为多态

1.1.2 什么是多态

多态的定义:计算机程序运行时,相同的消息可能会送给多个不同的类别之对象,而系统可依据对象所属类别,引发对应类别的方法,而有不同的行为。

这个定义很晦涩,可以从两个方面理解:

1、个体多态

  • 父类型定义的变量引用的子类型个体是多种多样的,如:Person变量可以引用Student、Teacher、Worker对象等
  • 个体多态是用向上造型实现的

2、行为多态

  • 父类型变量引用子类型实例后,执行方法时候可以得到多种结果,如:Person变量分别引用Student、Teacher、Worker对象时候执行schedule方法得到的结果不同
  • 行为多态是利用方法重写实现的

1.1.3 为什么需要多态

比如,有类关系如下图所示:

 

如何使用多态呢?首先多态的前提是继承,在有继承关系存在时候才能使用多态,其次是要对子类型进行统一处理,比如,所以人员都要执行计划。具体在实际开发中可以先不要考虑多态,先按照具体类型编程,当发现各种子类型都需要相同处理时候,再重构代码提升到父类型统一进行处理,这样就是多态处理了。比如:学生要执行计划schedule,教师要执行计划schedule,工人也要执行计划schedule,就统一装到Person数组中,用循环调用schedule方法一起执行计划。

1.1.4【案例】多态的基础应用示例

在上一个案例的基础上,测试行为多态。

案例示意代码如下:

public class PolyDemo1 {
    public static void main(String[] args) {
        // 使用父类引用指向子类对象 -> 子类向上造型
        Person p1 = new Student("Tom", 12);
        Person p2 = new Teacher("Andy", 28);
        Person p3 = new Worker("Jerry", 28);
        // 父类引用调用抽象方法,实际执行子类实现的方法
        // -> 行为多态
        p1.schedule();
        p2.schedule();
        p3.schedule();
        // 父类引用仅能访问父类中声明的成员
        // 父类应用无法访问子类中声明的成员
        // p1.study(); // 编译错误,无法访问
    }
}

1.1.5【案例】多态的扩展应用示例

在上一个案例的基础上,使用数组存储多个对象,统一执行其 schedule() 方法。

案例示意代码如下:

package oop_04.polymorphic;
public class PolyDemo2 {
    public static void main(String[] args) {
        // 多态数组
        Person[] array = {new Student("Tom", 12)
                            ,new Teacher("Andy", 28)
                            ,new Worker("Jerry", 28)};
        for(int i=0;i<array.length;i++) {
            test(array[i]);
        }
        Student s1=new Student("Lucy",15);
        // 子类类型的对象也可以传入该方法
        test(s1);
    }
    /**
     * 方法的参数为父类形态
     * 该父类的任意子类对象均可以传入该方法
     * @param person
     */
    public static void test(Person person){
        person.schedule();
    }
}

2 接口 interface

2.1 什么是接口

2.1.1 多继承问题

讨论接口之前,先看一个物品归类的生活实例:

 

查看这个商品分类,可看出:

1、相同类别的商品具有相似特征,且属性类似:比如“新鲜水果“类、”海鲜水产“类

2、同类标签便于管理统一存储和调度

3、也存在跨类别的分类标签:比如“地方特产“、”国际美食“

4、跨类别的分类标签体现了一个物品属于多种类型的现象,这种现象称为“多继承”

如果用 Java 代码来表现上述情况,会发现,Java的继承可以实现树形分类,但是无法处理跨类别标签:

 

不过,Java提供了接口,解决了跨类型的继承问题。

2.1.2 什么是接口

接口在JAVA编程语言中是一个抽象类型,通常以interface来声明。

从面向对象编程的角度,可以将接口理解为对不同类型的事物的共同的行为特征的抽象。例如,鹰和飞机属于不同类型的事物,但是都有飞行的行为特征。

 

可以把接口看成是特殊的抽象类。

2.1.3 接口和抽象类

抽象类和接口都属于抽象的概念,它们有一些区别,可以从同类别和跨类别的角度来考虑:

  • 同一种类别的公共行为和属性可以抽取到抽象类中。抽象类用于表示一种具有共性的类,可以包含实现的方法和具体的属性。比如,对于喜鹊和老鹰这两种鸟类,它们都属于鸟类的范畴,可以将它们共同的行为和属性抽象到一个抽象类(如Bird)中,以实现代码的重用和扩展。
  • 不同种类的公共行为可以抽取到接口中。接口用于定义一组相关的方法,用于表示某种能力或行为。比如,喜鹊、老鹰和飞机都具有起飞和着陆的功能,但它们并不属于同一种类,此时可以将与飞行相关的共同行为抽取到一个接口(如Flyable)中,不同类别的对象可以通过实现该接口来具备飞行的能力。

根据以上原则,对于喜鹊来说,它可以继承自抽象类Bird,以获取鸟类的共性属性和行为,并且还可以实现接口Flyable,以具备飞行的能力。

抽象类和接口的设计原则:

  • 将所有子类共有的方法抽象化到父类中,可以使用抽象类。
  • 将部分子类中的公共方法抽象化到接口中,适用于不同类别但具有相似行为的对象。

通过合理地使用抽象类和接口,可以实现代码的复用和扩展,并且更好地表示对象之间的关系和行为。选择使用抽象类还是接口取决于具体的设计需求和对象之间的关系。

2.2 接口的语法

2.2.1 接口的语法

使用interface定义接口:

1、接口中只能定义常量和方法

  • 可以省略常量的修饰词 public static final
  • 可以省略抽象方法修饰词 public abstract

2、接口不能实例化创建对象,

3、接口只能被继承,作为父类型被子类型实现

比如,定义飞行接口:

  • 包含常量ID
  • 包含 3 个抽象方法

代码结构示意如下:

 

2.2.2 实现接口

子类使用implements实现接口:必须实现该接口中所有的抽象方法。

具体语法如下所示:

 

一个类可以实现多个接口:实现的接口直接用逗号分隔。

具体语法如下所示:

 

2.2.3【案例】接口的示例

定义接口 Flyable 和类 Bird,并类 Plane实现接口Flyable,以及类 Eagle 继承Bird并实现Flyable;编写代码测试接口的用法。

案例示意代码如下所示:

package oop_04.interface01;
/**
 * 飞行接口
 */
public interface Flyable {
    int ID = 1;
    /**
     * 起飞
     */
    void takeOff();
    /**
     * 飞行
     */
    void fly();
    /**
     * 着陆
     */
    void land();
}
package oop_04.interface01;
public class Plane implements Flyable{
    @Override
    public void takeOff() {
        System.out.println("Plane takeOff...");
    }
    @Override
    public void fly() {
        System.out.println("Plane fly...");
    }
    @Override
    public void land() {
        System.out.println("Plane land...");
    }
}
package oop_04.interface01;
public class Bird {
    public void eat(){
        System.out.println("eat...");
    }
    public void sleep(){
        System.out.println("sleep...");
    }
}
package oop_04.interface01;
public class Eagle
        extends Bird implements Flyable{
    @Override
    public void takeOff() {
        System.out.println("Eagle takeOff...");
    }
    @Override
    public void fly() {
        System.out.println("Eagle fly...");
    }
    @Override
    public void land() {
        System.out.println("Eagle land...");
    }
}
package oop_04.interface01;
public class InterfaceDemo1 {
    public static void main(String[] args) {
        // Flyable flyable=new Flyable();  // 接口不可被实例化
        System.out.println(Flyable.ID);    // 接口中定义的是静态常量
        Flyable eagle = new Eagle();       // 接口类型引用指向实现类的对象
        eagle.fly();                       // 实际执行实现类重写的方法逻辑
        Flyable plane = new Plane();       // 接口类型引用指向实现类的对象
        plane.fly();                       // 实际执行实现类重写的方法逻辑
        // eagle.eat();                    // 无法访问实现类特有的方法
    }
}

2.3 接口与多继承

2.3.1 接口的继承

在Java中,接口之间也可以进行继承,这被称为接口的继承或接口的扩展。

接口的继承允许一个接口继承另一个接口的方法签名。通过继承,子接口可以获得父接口定义的方法签名,并且可以在子接口中添加新的方法签名。子接口继承了父接口的方法签名后,必须提供这些方法的具体实现。

接口的继承使用关键字extends,后面跟着要继承的父接口名称。一个接口可以继承多个接口,多个父接口之间使用逗号分隔。

下面是一个接口继承的示例:

interface Shape {
    void draw();
}
interface Circle extends Shape {
    double getRadius();
}
interface Colorable {
    void setColor(String color);
}
interface ColoredCircle extends Circle, Colorable {
    void rotate();
}

在上面的示例中,接口Circle继承了接口Shape,表示Circle接口扩展了Shape接口的方法签名。接口ColoredCircle继承了接口Circle和Colorable,表示ColoredCircle接口扩展了这两个父接口的方法签名,并且可以在子接口中添加新的方法签名rotate()。

接口的继承使得接口之间可以建立层次结构,从而实现方法签名的复用和组合。通过继承,我们可以定义更具体和特定的接口,以满足不同的需求和功能。

2.3.2 接口与多继承

接口与多继承的关系是一个常见的面试话题。在Java中,类只能继承自一个父类,这是单继承的限制。然而,一个类可以实现多个接口,这就允许了多继承的实现。

多继承的概念意味着一个类可以从多个父类继承属性和方法。然而,在Java中,类只能继承一个父类。这就是为什么Java引入接口的原因,以实现多继承的效果。通过实现多个接口,一个类可以获得多个接口定义的行为和功能,实现了类的多继承。

如下图所示:

 

在这个示例中,有三个接口:Person(人)、Flyable(可飞行)和Swimmable(可潜水)。

钢铁侠类实现了Person接口,并且还实现了Flyable和Swimmable接口。这意味着钢铁侠类具有Person接口定义的人的行为和属性,同时也具有Flyable接口定义的飞行行为和Swimmable接口定义的潜水行为。

通过实现多个接口,钢铁侠类获得了多个接口定义的行为和功能,实现了类的多继承效果。钢铁侠类可以同时表现出人的特征、飞行的能力和潜水的能力。

接口的多继承使得类可以在不受单继承限制的情况下,获得多个接口定义的功能,提供了更大的灵活性和可扩展性。

2.3.3 经典面试题目:接口和抽象类的区别

面试时候可以尝试从语法层面回复这个问题:

接口和抽象类在语法上有一些区别,主要涉及以下几个方面:

声明方式:抽象类使用 abstract 关键字进行声明,使用 class 关键字定义类。接口使用 interface 关键字进行声明。

继承关系:抽象类通过使用 extends 关键字继承其他类或抽象类。一个类只能继承一个抽象类。接口通过使用 implements 关键字实现一个或多个接口。一个类可以实现多个接口。

方法实现:抽象类可以包含实现的方法和抽象的方法。接口只能包含抽象的方法,不包含具体的方法实现。所有的方法都隐式地被声明为抽象方法,不需要使用 abstract 关键字。实现接口的类必须提供方法的具体实现。Java 8 引入了接口中的静态方法和默认方法,使得接口具备了一定的实现能力。

2.3.4 经典面试题目:Java如何实现多继承的

在Java中,类是单继承的,即一个类只能继承自一个父类。然而,通过接口的使用,Java可以实现多继承的效果。类可以实现多个接口中的方法,从而获得多个接口定义的行为和功能。这种机制提供了灵活性和可扩展性,使得Java在面对多继承需求时能够更好地满足设计和开发的需要。

3 造型

3.1 向上造型

3.1.1 向上造型

向上造型(Upcasting)是指将一个子类对象赋值给父类引用变量的过程。通过向上造型,可以将一个子类对象视为其父类类型,实现多态性的体现。

向上造型的特点:

  • 子类对象可以赋值给父类引用变量,但是父类对象不能赋值给子类引用变量。
  • 向上造型是自动进行的,不需要额外的转换操作。
  • 通过向上造型,可以调用父类中声明的方法,但无法调用子类中特有的方法。

向上造型的优势:

  • 实现多态性:通过向上造型,可以将不同子类的对象视为父类类型,统一对待,实现多态性的效果。
  • 灵活性和扩展性:通过向上造型,可以在不改变父类引用的情况下,使用不同的子类对象,使程序具备更大的灵活性和可扩展性。

3.1.2 【案例】向上造型示例

示例代码:

class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void printInfo() {
        System.out.println("Person: " + name);
    }
}
class Student extends Person {
    private int studentId;
    public Student(String name, int studentId) {
        super(name);
        this.studentId = studentId;
    }
    public int getStudentId() {
        return studentId;
    }
    public void printInfo() {
        System.out.println("Student: " + getName() + ", Student ID: " + studentId);
    }
}
class Teacher extends Person {
    private String subject;
    public Teacher(String name, String subject) {
        super(name);
        this.subject = subject;
    }
    public String getSubject() {
        return subject;
    }
    public void printInfo() {
        System.out.println("Teacher: " + getName() + ", Subject: " + subject);
    }
}
public class Main {
    public static void main(String[] args) {
        Person person1 = new Student("Alice", 123);
        Person person2 = new Teacher("Bob", "Math");
        person1.printInfo(); // 输出: Student: Alice, Student ID: 123
        person2.printInfo(); // 输出: Teacher: Bob, Subject: Math
        // 向上造型
        Person person3 = new Student("Carol", 456);
        Person person4 = new Teacher("David", "Science");
        person3.printInfo(); // 输出: Student: Carol, Student ID: 456
        person4.printInfo(); // 输出: Teacher: David, Subject: Science
    }
}

在上述示例中,Person是一个基类,Student和Teacher是其子类。我们可以将Student和Teacher对象向上造型为Person类型,并将它们赋值给Person引用变量person3和person4。通过向上造型,我们可以使用Person引用变量调用Person类中的方法和属性。在调用printInfo()方法时,由于方法被子类重写,实际上会根据对象的实际类型调用相应的子类方法。

这样做的好处是,我们可以使用统一的Person类型处理不同类型的对象,实现了多态性。通过向上造型,我们可以灵活地处理不同类型的子类对象,使代码更具扩展性和可维护性。

3.2 向下造型

3.2.1 向下造型

向上造型中有个特性“无法调用子类中特有的方法”,如果调用子类行特有的方法呢?这个就需要使用向下造型了。

向下造型(Downcasting)是指将一个已经向上造型(Upcasting)的对象重新转回其原始的子类类型。它允许我们在需要的时候访问和调用子类特有的方法和属性。

3.2.2【案例】向下造型示例

在 Java 中,向下造型需要使用强制类型转换操作符(子类类型)来实现,但在进行向下造型之前,需要先确保对象实际上是指定的子类对象。否则,如果尝试对一个不兼容的对象进行向下造型,将会抛出ClassCastException异常。

以下是一个示例,演示了向下造型的使用:

/**
 * 演示向下转型
 */
public class Demo02 {
    public static void main(String[] args) {
        Person person1 = new Student("Alice", 123);
        Person person2 = new Teacher("Bob", "Math");
        // 直接使用类型引用调用子类特有的方法会编译错误
        // person1.getStudentId(); // 编译错误
        // person2.getSubject(); // 编译错误
        
        // 向下转型
        Student student = (Student) person1;
        Teacher teacher = (Teacher) person2;
        System.out.println(student.getStudentId()); // 输出: 123
        System.out.println(teacher.getSubject()); // 输出: Math
        
        // 向下转型时,如果类型不匹配,会抛出ClassCastException
        // Teacher teacher2 = (Teacher) person1; // 抛出ClassCastException
    }
}

需要注意的是,在进行向下造型之前,我们需要确保对象实际上是指定的子类对象。否则,如果尝试对一个不兼容的对象进行向下转型,将会导致运行时异常。

向下转型的使用需要谨慎,应确保转型操作的合法性和正确性。如果不确定对象是否适合进行向下转型,可以使用instanceof运算符进行类型检查,以避免可能的异常。

3.2.3 instanceof 运算

instanceof 运算符用于检测对象是否是指定类型的实例。它经常与向下造型一起使用,以实现类型安全的转换,避免类型转换异常的发生。

instanceof 运算符的语法如下:

对象 instanceof 类型

其中,对象是要检测的对象,类型是要检测的类名或接口名。

instanceof 运算符返回一个布尔值,如果对象是指定类型的实例,则返回 true,否则返回 false。

下面是一个示例,演示了instanceof 运算符的使用:

Person person1 = new Student("Alice", 123);
Person person2 = new Teacher("Bob", "Math");
// 使用instanceof运算符判断对象是否是某个类的实例
System.out.println(person1 instanceof Student); // 输出: true
System.out.println(person1 instanceof Person);  // 输出: true
System.out.println(person1 instanceof Teacher); // 输出: false
System.out.println(person2 instanceof Student); // 输出: false

在上述示例中,我们创建了一个 Person 类的实例 person1,它实际上是一个 Student 对象。使用 instanceof 运算符可以判断 person1 是否是 Student 类的实例,结果为 true。同样地,我们也可以判断 person1 是否是 Person 类的实例,结果同样为 true。然而,由于 person1 并不是 Teacher 类的实例,所以返回 false。

使用 instanceof 运算符可以帮助我们在进行类型转换之前先进行类型检测,确保转换的安全性。这样可以避免类型转换异常的发生,并在需要时选择执行相应的操作。

3.2.4使用instanceof保护造型

使用 instanceof 运算符可以保护向下造型,避免 ClassCastException 异常的发生,从而减少程序中的运行错误。

在使用 instanceof 运算符进行向下造型时,可以先使用 instanceof 进行类型检测,以确保对象的类型与要转型的类型匹配。如果匹配成功,就可以进行转型操作,否则可以选择执行其他逻辑或抛出异常。

下面是一个示例,演示了如何使用 instanceof 运算符保护向下造型:

if (person1 instanceof Student) {
    Student student = (Student) person1;
    System.out.println(student.getStudentId()); // 输出: 123
}

在上述示例中,我们先使用 instanceof 运算符检测 person1 是否是 Student 类的实例。如果匹配成功,我们就可以将 person1 强制转型为 Student 类型,并调用 getStudentId() 方法。这样可以避免在转型过程中发生 ClassCastException 异常。

此外,Java 17 引入了 instanceof 模式匹配的新特性,可以进一步简化向下转型的编码:

if (person1 instanceof Student student) {
    System.out.println(student.getStudentId()); // 输出: 123
}

在上述示例中,我们使用 instanceof 模式匹配,将匹配成功的结果直接绑定到 student 变量上,省去了显式的类型转换操作。这样可以更加简洁地实现向下转型,并且代码更加清晰易读。

使用 instanceof 运算符和 instanceof 模式匹配可以提高程序的健壮性,确保类型转换的安全性,减少潜在的运行时错误。

4 内部类

4.1 内部类概述

4.1.1 内部类概述

内部类,顾名思义,就是声明在一个外部类内部的类。内部与外部,是一个相对的说法:外部类是指内部类所在的类。

内部类一般有以下4种分类:

  • 局部内部类:声明在外部类的局部位置上,有类名
  • 成员内部类:声明在外部类的成员位置上,有类名,无static修饰
  • 静态内部类:声明在外部类的成员位置上,有类名,有static修饰
  • 匿名内部类:在一行代码上继承父类并且创建出子类实例的语法,无类名

如下图所示:

上述4种内部类中,匿名内部类在日常开发中较为常见,将在本节中进行介绍。其他的内部类在基础的开发中较为少见,在一些特定的设计模式和框架中有所应用,将在后续的课程中进行介绍。

4.2 匿名内部类

4.2.1 什么是匿名内部类

如果在一段程序中需要创建一个类的对象(通常这个类需要实现某个接口或者继承某个类),而且对象创建后,这个类的价值也就不存在了,这个类可以不必命名,称之为匿名内部类。

利用匿名内部类可以写出简洁明快的代码,在实际开发中应用非常广泛。

语法示例如下:

 

4.2.2 使用匿名内部类

匿名内部类的语法在一行代码上完成了两个功能:继承父类,创建子类行对象,所以要有1个前提条件:有一个可以被继承的父类型, 这个父类型可以是类、抽象类、接口。如下所示:

 

利用匿名内部类,可以在一行代码上继承父类并且创建出子类实例。这样可以使用最简洁的代码实现最多的功能。由于利用匿名内部类可以写出简洁明快的代码,在实际开发中应用非常广泛。

比如存在一个父类Bird:

 如果需要创建一个子类重写其move方法,对比一下普通类和匿名内部类的区别:

 

显然,匿名内部类显得更加简洁方便。匿名内部类简洁地省略类子类类名,也因为没有类名造成不能再复用类名创建更多地对象。在使用匿名内部类时候要注意:

1、如果只是简洁地继承父类,并且只需要创建一个子类对象,就采用匿名内部类。

2、如果子类需要反复使用创建一组子类对象就采用普通的子类。

3、匿名内部类一定是子类,一定需要有父类型时候才能使用。

4、匿名内部类的最大优点就是语法简洁,在一行上继承子类并且创建类了子类对象。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python 使用linux find命令引导用户定位和选择文档

字多不看板&#xff08;InsCode&#xff09; 演示代码 # -*- coding:UTF-8 -*-# region import DebugInfo from DebugInfo.DebugInfo import *# endregion 画板 打印模板()# localSearch posix搜索接口类() localSearch 本地搜索接口类()用户选择 交互接口类.指定选择文档(…

.Net Reactor 使用心得

主密钥是干嘛的&#xff1f; 1 若要创建有效的许可证文件&#xff0c;必须使用与用于生成受.NET Reactor保护的输出相同的主密钥来创建许可证。 2 主密钥是在创建项目时生成的&#xff01;必须保存该项目才能保留原始密钥。 dll而不是exe 由于使用的是.net6 生成的代码。 …

颠倒二进制位

题目链接 颠倒二进制位 题目描述 注意点 输入是一个长度为 32 的二进制字符串 解答思路 可以灵活运用位运算对二进制位进行颠倒&#xff0c;思路为&#xff1a;从后往前判断第i位是否为1&#xff0c;判断第i位是否为1可以将其二进制右移i位后与1进行&操作&#xff0c;…

掌握Web、DNS、FTP、DHCP服务器的配置。掌握简单网络方案的规划和设计

1、Web服务器配置 2、综合设计 配置完后,所有的终端主机都要能够访问外网服务器,并进行测试。(本题可以自行选题,自行设计,但必须包含路由器、服务器(web、dns、DHCP、)、交换机及防火墙)。 3.做好规划并搭建拓扑图: 4.给PC机与服务器配置好IP,网关 5.给每个交换机…

EasyRecovery2024功能强大且专业的mac电脑数据恢复程序

EasyRecovery15是一款功能强大且专业的IOS数据恢复程序&#xff0c;专为在iPhone&#xff0c;iPad和iPod touch上检索丢失的照片&#xff0c;消息&#xff0c;音乐等而设计。无论您是错误删除还是意外丢失了对您来说重要的任何内容&#xff0c;EasyRecovery都会帮助您找回它们。…

基于深度学习的人脸测距&社交距离过近警报系统

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 近年来&#xff0c;随着深度学习技术的快速发展&#xff0c;人脸识别技术在各个领域得到了广泛应用。其中&#xff0c;人脸测距和社交距离过近警报系统成为了人们…

C语言:指向数组的指针和指向数组元素的指针

相关阅读 C语言https://blog.csdn.net/weixin_45791458/category_12423166.html?spm1001.2014.3001.5482 指向数组的指针和指向数组元素的指针常常被混淆&#xff0c;或者笼统地被称为数组指针&#xff0c;但它们之间是有差别的&#xff0c;本文就将对此进行讨论。 下面的代码…

IPO:“动储结合”抢占储能先机后,瑞浦兰钧如何继续赢?

在全球新能源汽车的推动下&#xff0c;锂电池赛道早已拥挤不堪&#xff0c;作为入局较晚的后起之秀&#xff0c;从2017年成立到首次实现锂电池的批量交付&#xff0c;瑞浦兰钧能源股份有限公司&#xff08;以下简称“瑞浦兰钧”&#xff09;仅用了2年不到的时间。2022年&#x…

如何通过TortoiseGit可视化工具查看Git管理的版本树和信息(工作树变更)内容

一、版本树 黑色直线&#xff1a;master分支和基于master分支拉取基础分支都在这条线上&#xff0c;是一条直线。 其他线条&#xff1a;新开分支一定会增加一条线&#xff0c;但不一定每一条线分别代表一个分支。 注&#xff1a;如果一直是一个人&#xff0c;在同一个本地分支…

解决GateWay报错:Exceeded limit on max bytes to buffer : 262144

场景&#xff1a; 前端传来了一个大的字符串 发现请求不通 一番调试发现SpringGateway 默认内存缓冲区262144字节 网上查了很多种常见的解决方案无效之后 直接重写底层 网友的解决方案 方案1&#xff08;无效&#xff09; 直接修改缓冲区大小 spring:codec:max-in-memory-s…

Apache OfBiz 反序列化命令执行漏洞(CVE-2023-49070)

项目介绍 Apache OFBiz是一个非常著名的电子商务平台&#xff0c;是一个非常著名的开源项目&#xff0c;提供了创建基于最新J2EE/XML规范和技术标准&#xff0c;构建大中型企业级、跨平台、跨数据库、跨应用服务器的多层、分布式电子商务类WEB应用系统的框架。OFBiz最主要的特…

Shopify模版二次开发 Liquid实现响应式无缝跑马灯效果

1、HTML 代码结构 要实现无缝&#xff0c;我们需要复制出文案结构放在后面 <div class"marquee__wrapper"><div class"marquee"><div class"marquee__content"><p>有人知道在 Shopify 中使用media 的正确方法吗&#x…

数据链路层的作用和三个基本问题

目录 一. 数据链路层的作用二. 数据链路层解决的三个问题2.1 数据链路和帧2.2 三个基本问题(重要)2.2.1 封装成帧2.2.2 透明传输2.2.3 差错检测 \quad 一. 数据链路层的作用 \quad \quad \quad 光有链路不能传输数据, 还要加上协议, 这样才是数据链路 数据链路层的作用就是负责…

CVPR 2023 三维重建相关必读论文和代码合集

三维重建涉及将二维图像或视频转换为三维模型的过程&#xff0c;这个过程需要应用到多门学科的知识&#xff0c;比如数学、计算机图形学和多视图几何等&#xff0c;学习门槛较高。但尽管如此&#xff0c;三维重建仍然是CV领域的一个热门方向。 目前三维重建技术已经有了广泛应…

基于YOLOv8深度学习的吸烟/抽烟行为检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

桥梁巡查管理二维码

随着互联网世界的发展&#xff0c;二维码随处可见。二维码已经融入到我们生活的各个方面&#xff0c;不管是买东西&#xff0c;还是参观展览&#xff0c;甚至当我们走在路上&#xff0c;路牌上都会有二维码。甚至很多桥梁都用二维码来管理。 使用二维码管理桥梁能实现哪些功能…

有监督学习、无监督学习、半监督学习和强化学习

有监督学习 训练数据有标签 无监督学习 数据是没有标签的 聚类的思想&#xff1a;通过计算空间中的距离来判断是否属于同一类 强化学习 和环境交互&#xff0c;从环境中学习 三者对比 半监督学习 少量有标注&#xff0c;大量无标注 三个假设 1.连续性/平滑性假设:相…

肥猫游戏报价器|计价器|王者荣耀代练陪练等游戏报价器软件介绍说明

目录 1. 前言2. 软件著作权3. 软件使用说明3.1 进入软件3.2 用户登录3.3 首页3.4 报价器3.4.1 总体介绍3.4.2 王者报价器3.4.3 LOL手游报价器3.4.4 英雄联盟报价器3.4.5 云顶之弈报价器3.4.7 王者水晶报价器3.4.8 和平精英报价器3.4.9 蛋仔派对报价器3.4.10 穿越火线报价器3.4.…

验证栈序列(栈压入、弹出序列),剑指offer,力扣

目录 题目地址&#xff1a; 相同题型&#xff1a; 我们直接看题解吧&#xff1a; 解题方法&#xff1a; 审题目事例提示&#xff1a; 解题分析&#xff1a; 解题思路&#xff1a; 代码实现&#xff1a; 题目地址&#xff1a; 946. 验证栈序列 - 力扣&#xff08;LeetCode&#…

想入门Web测试,看这篇文章!

今天要谈的是很多软件测试工程师都需要面对的——Web测试 不管你是处在二十不惑的青春有你阶段还是三十而已的乘风破浪阶段我们都需要面对“Web测试”。 Web测试其实有以下几个方面&#xff1a; 1、页面测试 大多数的Web网站的网页都是html语言编写的&#xff0c;测试工程师…