Java泛型详解:为什么使用泛型?如何使用泛型?

news2024/11/18 1:30:28

Java泛型详解:为什么使用泛型?如何使用泛型?

  • 💘一、为什么使用泛型?
  • 💘二、如何使用泛型?
    • 💖1. 泛型类的使用:
    • 💖2. 泛型方法的使用:
    • 💖3. 泛型接口的使用:
  • 💘三、泛型通配符 ?
    • 💖 1. extends通配符
    • 💖2. super通配符
  • 💘四、泛型的实现原理和本质

在这里插入图片描述

博主 默语带您 Go to New World.
个人主页—— 默语 的博客👦🏻
《java 面试题大全》
🍩惟余辈才疏学浅,临摹之作或有不妥之处,还请读者海涵指正。☕🍭
《MYSQL从入门到精通》数据库是开发者必会基础之一~
🪁 吾期望此文有资助于尔,即使粗浅难及深广,亦备添少许微薄之助。苟未尽善尽美,敬请批评指正,以资改进。!💻⌨

大家好!今天我要和大家一起探讨的是Java泛型,一个让我们的代码更加灵活、可读性更强的强大特性。相信很多人都听说过泛型,但对于为什么使用泛型、如何使用泛型以及泛型的实现原理和本质,可能还有些困惑。别担心,我会通过通俗易懂的语言,带你深入了解这一话题,并为你提供一些实例演示。

前言:

大家好!,今天我将为大家介绍一个非常有趣的话题——泛型。作为Java语言中的一项重要特性,泛型可以让我们编写更加通用和灵活的代码。无论您是刚入门Java编程,还是已经有一定经验的开发者,了解泛型都对您的编程能力有所帮助。本文将深入探讨泛型的实现原理和本质,帮助您更好地理解并应用泛型。现在就让我们一起来探索吧!

摘要:

泛型是Java语言中一项非常强大的特性,它可以让我们编写更加通用和灵活的代码。然而,泛型的实现原理和本质却常常被开发者们所忽视。本文将通过实例和原理解析,详细介绍泛型在Java中的实现机制——类型擦除。我们将深入探讨在编译时泛型类型信息如何被擦除,以及如何保持代码的向后兼容性。此外,我们还将讨论在使用泛型时需要注意的一些问题,并给出一些建议和实用技巧。通过阅读本文,您将对泛型有一个更清晰、更全面的了解,并能够更加自信地运用它来提升您的编程能力。让我们开始这个有趣的泛型之旅吧!

在这里插入图片描述

💘一、为什么使用泛型?

泛型的好处可以总结为三个关键词:类型安全、代码复用和可读性

首先,泛型可以保证类型安全。通过使用泛型,我们可以在编译阶段就捕获类型错误,而不是在运行时才发现。这可以避免很多潜在的bug,使我们的代码更加可靠。

其次,泛型可以提高代码复用性。以集合类为例,我们可以定义一个泛型类,使其适用于不同类型的数据。这样一来,我们就不需要为每一种类型都编写一个独立的类,大大简化了代码的编写和维护。

最后,泛型还可以提升代码的可读性。通过在代码中使用泛型,我们可以清楚地看到数据的类型,从而更好地理解代码的含义和逻辑。这对于团队合作或长期维护代码来说非常重要。


让我通过一个简单的示例来说明为什么使用泛型。

假设我们有一个名为"Box"的类,用于存储不同类型的数据。在没有泛型的情况下,我们可能会这样定义这个类:

public class Box {
    private Object content;

    public Box(Object content) {
        this.content = content;
    }

    public Object getContent() {
        return content;
    }

    public void setContent(Object content) {
        this.content = content;
    }
}

在这个示例中,我们使用了Object类型来存储数据。但是,当我们取出数据时,我们需要进行类型转换:

Box stringBox = new Box("Hello");
String content = (String) stringBox.getContent();

这个类型转换可能会导致运行时的错误,比如"ClassCastException"异常。而且,在代码的阅读和理解过程中,我们可能不清楚"getContent()"返回的具体类型是什么,需要通过文档或注释来获得更多信息。


现在,让我们来看看使用泛型会给我们带来什么好处:

public class Box<T> {
    private T content;

    public Box(T content) {
        this.content = content;
    }

    public T getContent() {
        return content;
    }

    public void setContent(T content) {
        this.content = content;
    }
}

在这个示例中,我们使用泛型类型参数T来替代Object类型。这样一来,我们可以在实例化Box对象时指定具体的类型,比如String、Integer等。

Box<String> stringBox = new Box<>("Hello");
String content = stringBox.getContent(); // 不需要进行类型转换

通过使用泛型,我们可以获得以下好处:

1. 类型安全:在编译时就能发现类型错误,避免了运行时的类型转换错误。
2. 代码复用:我们可以将相同逻辑的代码应用于不同类型的数据,不需要为每种类型都编写一个独立的类。
3. 可读性:通过在代码中使用泛型,我们可以清晰地看到数据的类型,更好地理解代码的含义和逻辑。


总结起来,使用泛型可以让我们的代码更加类型安全、可读性更强、更具复用性。它是提高代码质量和可维护性的强大工具。希望这个示例能够帮助你理解为什么使用泛型。如果还有任何疑问,欢迎继续提问!


当然!除了我之前提到的类型安全、代码复用和可读性外,使用泛型还有其他一些好处。
假设我们需要编写一个通用的打印方法,可以打印出任意类型的数据。在没有泛型的情况下,我们可能会这样实现:

public class Printer {
    public void printString(String data) {
        System.out.println(data);
    }
    
    public void printInteger(Integer data) {
        System.out.println(data);
    }
    
    public void printDouble(Double data) {
        System.out.println(data);
    }
}

在这个示例中,我们需要为不同类型的数据编写多个重载的方法,这样会导致代码冗长和重复。而且,当我们需要打印其他类型的数据时,还需要继续添加新的重载方法。

现在,让我们看看如何使用泛型来改进这个示例:

public class Printer<T> {
    public void print(T data) {
        System.out.println(data);
    }
}

通过使用泛型类型参数T,我们只需要编写一个通用的print方法,可以接受任意类型的数据并进行打印。

Printer<String> stringPrinter = new Printer<>();
stringPrinter.print("Hello");

Printer<Integer> integerPrinter = new Printer<>();
integerPrinter.print(123);

Printer<Double> doublePrinter = new Printer<>();
doublePrinter.print(3.14);

通过实例化泛型类Printer,并在尖括号中指定具体的类型参数,我们可以创建不同类型数据的打印机对象。然后,我们可以使用通用的print方法来打印不同类型的数据,无需编写重复的代码。

除了减少代码数量和重复工作外,使用泛型还有以下好处:

4. 强制类型检查:通过在编译时进行类型检查,可以尽早地捕获类型错误,确保数据类型的正确性。
5. 减少类型转换:使用泛型可以避免我们在代码中进行频繁的类型转换。这不仅提高了代码的可读性,还可以提高代码的性能。


总结起来,使用泛型可以让我们的代码更加简洁、类型安全、可读性更强,并避免了重复的工作。它是提高代码质量和可维护性的重要工具。

💘二、如何使用泛型?

在Java中,使用泛型有三种方式:泛型类和泛型方法,泛型接口。

  1. 泛型类:我们可以通过在类的定义中使用< >来指定一个或多个类型参数,用于代替具体的类型。比如,我们可以定义一个泛型类Box,其中T是一个占位符,代表某种具体的类型。通过在实例化时指定类型参数,我们可以创建一个具体类型的对象。

  2. 泛型方法:除了在类级别上使用泛型,我们还可以在方法级别上使用泛型。通过在方法的返回值类型前面加上< >,我们可以定义一个泛型方法。在使用该方法时,可以在方法调用的实参中指定具体的类型。

  3. 泛型接口(Generic Interface):通过在接口的定义中使用类型参数来代表具体的类型。实现该接口的类需要指定具体的类型参数。


当使用泛型时,我们可以在类或方法的定义中使用泛型类型参数来代表具体的类型。下面我将分别介绍泛型类和泛型方法;

💖1. 泛型类的使用:

泛型类可以在类的定义中使用类型参数来代表具体的类型。通过在实例化类时指定类型参数,我们可以创建具有不同类型的对象。下面是一个示例代码:

public class Box<T> {
    private T content;
    
    public Box(T content) {
        this.content = content;
    }
    
    public T getContent() {
        return content;
    }
    
    public void setContent(T content) {
        this.content = content;
    }
}

// 创建具有不同类型的Box对象
Box<String> stringBox = new Box<>("Hello");
System.out.println(stringBox.getContent()); // 打印输出: Hello

Box<Integer> intBox = new Box<>(123);
System.out.println(intBox.getContent()); // 打印输出: 123

在这个示例中,我们创建了一个名为Box的泛型类。我们可以在实例化Box对象时,通过尖括号指定具体的类型参数,比如String和Integer。然后我们可以使用泛型方法getContent()来获取相应类型的数据。

通过使用泛型类,我们可以实现类型安全、代码复用和可读性等好处。同时,我们可以避免进行类型转换,减少潜在的错误。泛型类是非常常见且强大的泛型应用方式。

💖2. 泛型方法的使用:


泛型方法可以在方法的定义中使用类型参数来代表具体的类型。通过在方法返回类型之前使用尖括号定义类型参数,我们可以编写出可以适用于不同类型数据的通用方法。下面是一个示例代码:

public class Printer {
    public <T> void print(T data) {
        System.out.println(data);
    }
}

// 使用泛型方法打印不同类型的数据
Printer printer = new Printer();
printer.print("Hello"); // 打印输出: Hello

printer.print(123); // 打印输出: 123

printer.print(3.14); // 打印输出: 3.14

在这个示例中,我们创建了一个名为Printer的类,其中包含一个名为print的泛型方法。我们可以在方法的返回类型之前使用尖括号定义类型参数T。然后我们可以通过调用print方法,并传递不同类型的数据来实现打印。

通过使用泛型方法,我们可以为不同类型的数据编写通用的操作方法,而不必为每种数据类型都编写一个独立的方法。这大大提高了代码的复用性和可读性。

💖3. 泛型接口的使用:

当我们需要定义一个可以适用于不同类型的接口时,就可以使用泛型接口。下面是一个示例代码,演示了如何使用泛型接口:

// 定义泛型接口
public interface Box<T> {
    T getContent();
    void setContent(T content);
}

// 实现泛型接口
public class StringBox implements Box<String> {
    private String content;
    
    public String getContent() {
        return content;
    }
    
    public void setContent(String content) {
        this.content = content;
    }
}
// 使用泛型接口
public class Main {
    public static void main(String[] args) {
        Box<String> stringBox = new StringBox();
        stringBox.setContent("Hello, World!");
        
        String content = stringBox.getContent();
        System.out.println(content); // 输出:Hello, World!
    }
}

在上述示例中,我们定义了一个简单的泛型接口 Box,该接口有两个方法:getContentsetContent。这个接口使用类型参数 T 来代表具体的内容类型。

然后,我们创建一个实现了泛型接口 Box 的类 StringBox,这个类指定了泛型类型为 String。在 StringBox 类中,我们用一个私有字段 content 存储字符串内容,并实现了接口的两个方法。

最后,在 Main 类的 main 方法中,我们创建了一个 StringBox 对象,并将字符串内容设置为 “Hello, World!”。然后,我们使用 getContent 方法获取内容,并将其打印输出。


// 定义泛型接口
public interface List<E> {
    void add(E element);
    E get(int index);
}

// 实现泛型接口
public class MyList<T> implements List<T> {
    private T[] elements;
    private int size;
    
    public MyList(int capacity) {
        elements = (T[]) new Object[capacity];
        size = 0;
    }
    
    public void add(T element) {
        if (size < elements.length) {
            elements[size++] = element;
        } else {
            // 处理数组已满的情况
        }
    }
    
    public T get(int index) {
        if (index < size) {
            return elements[index];
        } else {
            // 处理索引越界的情况
            return null;
        }
    }
}

// 使用泛型接口
public class Main {
    public static void main(String[] args) {
        List<String> stringList = new MyList<>(10);
        stringList.add("Hello");
        stringList.add("World");
        
        String firstElement = stringList.get(0);
        String secondElement = stringList.get(1);
        
        System.out.println(firstElement); // 输出:Hello
        System.out.println(secondElement); // 输出:World
    }
}

在上面的示例中,我们首先定义了一个泛型接口 List,该接口有两个方法:addget,分别用于向列表中添加元素和获取指定索引位置的元素。

然后,我们创建了一个实现泛型接口的类 MyList,该类使用类型参数 T 来代表具体的元素类型。在 MyList 类中,我们使用一个数组来存储元素,并实现了 addget 方法来添加和获取元素。

Main 类的 main 方法中,我们创建了一个 MyList 对象,并指定了元素类型为 String。然后,我们使用 add 方法向列表中添加了两个字符串元素。最后,我们使用 get 方法获取指定索引位置上的元素,并将其打印输出。

通过使用泛型接口,我们可以创建可适用于不同类型的列表对象,提高代码的可重用性和灵活性。

总结起来,泛型类和泛型方法都是灵活且强大的工具,在处理不同类型数据时提供了更加通用和灵活的方式。通过使用泛型,我们可以使代码更加简洁、类型安全,减少代码的重复工作。希望这个示例能帮助大家理解如何使用泛型。如果还有其他问题,请随时私信!


💘三、泛型通配符 ?

有时候,我们会遇到一种情况,即希望传入的类型可以是某种特定类型的子类型,但又不确定具体是哪个子类型。这时,我们可以使用泛型通配符"?"。

💖 1. extends通配符

用来限制泛型的上界。比如,List<? extends Number>表示可以接受的类型是Number及其子类型。

💖2. super通配符

用来限制泛型的下界。比如,List<? super Integer>表示可以接受的类型是Integer及其父类型。

当我们使用泛型时,有时候我们可能会遇到一种情况,即希望可以接收任意类型的参数。这时候就可以使用泛型通配符,表示未知的类型。下面我将详细说明泛型通配符的用法,并提供一个示例代码:

泛型通配符可以用作泛型类型参数的替代,表示该位置可以接受任意类型的实参。它提供了一种灵活的方式来处理未知类型的情况。

1. 通配符作为方法的参数:

public void printList(List<?> list) {
    for (Object item : list) {
        System.out.println(item);
    }
}

在这个示例中,printList方法接受一个List类型的参数,但是该List可以包含任意类型的元素。我们使用通配符?来表示未知的类型。在方法内部,我们可以通过遍历列表打印出列表中的每个元素。

2. 通配符作为方法的返回类型:

public List<?> getList() {
    return new ArrayList<>();
}

在这个示例中,getList方法返回一个List类型的对象,但是该List可以包含任意类型的元素。同样地,我们使用通配符?表示未知的类型。该方法可以根据实际需求返回不同类型的列表。

通过使用泛型通配符,我们可以编写更加灵活和通用的代码,尤其是当我们不确定要处理的类型时。使用通配符可以使我们的代码更具有可重用性和扩展性。

下面是一个示例代码,演示了如何使用泛型通配符

public static void printList(List<?> list) {
    for (Object item : list) {
        System.out.println(item);
    }
}

public static void main(String[] args) {
    List<String> stringList = Arrays.asList("Hello", "World");
    List<Integer> integerList = Arrays.asList(1, 2, 3);
    
    printList(stringList); // 打印输出: Hello World
    printList(integerList); // 打印输出: 1 2 3
}

main方法中,我们创建了一个String类型的列表和一个Integer类型的列表。然后,我们调用printList方法来打印这两个列表的元素。由于printList方法使用的是泛型通配符,所以可以接受不同类型的列表作为参数。

💘四、泛型的实现原理和本质

在Java中,泛型并不是完全的类型擦除,它通过类型擦除来实现。在编译时,所有的泛型类型参数都会被擦除,用它们的上界类型来替代。这样一来,在运行时,泛型的类型信息是不可见的。不过,通过反射机制,我们仍然可以获取到泛型的一些信息。

泛型的本质是参数化类型,它让我们能够在编译阶段指定类型关系,从而提供更好的类型检查和安全性。

泛型是Java语言中一项非常强大的特性,它可以让我们编写更加通用和灵活的代码。那么,让我们来详细说明一下泛型的实现原理和本质。

在Java中,泛型的实现原理基于类型擦除(Type Erasure)机制。这意味着在编译时,所有的泛型类型信息都会被擦除,即泛型参数会被替换为它们的上界类型(或者是Object类型)。这样做的目的是为了保持代码的向后兼容性,因为Java使用的是虚拟机运行环境,而不是直接运行Java源代码。

让我们看一个简单的示例来理解泛型的实现原理:

public class MyGenericClass<T> {
    private T value;
    
    public T getValue() {
        return value;
    }
    
    public void setValue(T value) {
        this.value = value;
    }
    
    public static void main(String[] args) {
        MyGenericClass<String> stringObj = new MyGenericClass<>();
        stringObj.setValue("Hello, World!");
        
        MyGenericClass<Integer> integerObj = new MyGenericClass<>();
        integerObj.setValue(42);
        
        String stringValue = stringObj.getValue();
        Integer integerValue = integerObj.getValue();
        
        System.out.println(stringValue); // 输出:Hello, World!
        System.out.println(integerValue); // 输出:42
    }
}

在上述示例中,我们定义了一个泛型类 MyGenericClass,它可以接受任意类型的参数。在类内部,我们使用类型参数 T 来表示具体的类型。我们创建了两个对象 stringObjintegerObj,分别指定了泛型参数为 StringInteger

在编译时,Java编译器会进行类型擦除并生成相应的字节码。在这个过程中,所有的泛型类型信息都被擦除,代码中的泛型参数 T 被替换为它们的上界类型(或者是Object类型)。也就是说,编译后的代码会变成:

public class MyGenericClass {
    private Object value;
    
    public Object getValue() {
        return value;
    }
    
    public void setValue(Object value) {
        this.value = value;
    }
    
    public static void main(String[] args) {
        MyGenericClass stringObj = new MyGenericClass();
        stringObj.setValue("Hello, World!");
        
        MyGenericClass integerObj = new MyGenericClass();
        integerObj.setValue(42);
        
        String stringValue = (String) stringObj.getValue();
        Integer integerValue = (Integer) integerObj.getValue();
        
        System.out.println(stringValue); // 输出:Hello, World!
        System.out.println(integerValue); // 输出:42
    }
}

从上述代码可以看出,所有的泛型类型 T 都被替换为了 Object 类型。在获取值的时候,由于类型信息被擦除,我们需要进行类型转换。

需要注意的是,尽管在运行时泛型参数的类型被擦除了,但是在编译阶段,Java编译器会检查泛型的类型安全性,并生成相应的编译器警告或错误。

我们可以总结一下泛型的本质:泛型是一种在编译时期对类型进行检查和保证的机制,通过类型擦除实现了对不同类型的通用操作,在运行时使用了类型转换来保证类型的正确性。

希望这个详细说明能够帮助您理解泛型的实现原理和本质!如果还有其他问题,请随时提问。

希望通过这篇文章,你对Java泛型有了更深入的了解。泛型是一个非常强大的特性,它可以提高我们代码的安全性、复用性和可读性。在实际开发中,我们可以充分利用泛型来提高代码质量。!

如对本文内容有任何疑问、建议或意见,请联系作者,作者将尽力回复并改进📓;(联系微信:Solitudemind )

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

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

相关文章

什么是ABP?

1、ABP背后的思想——DDD&#xff08;领域驱动设计&#xff09; ABP架构&#xff1a; ABP实现了多层架构&#xff08;领域层&#xff0c;应用层&#xff0c;基础设施层和表示层&#xff09;&#xff0c;以及领域驱动设计&#xff08;实体&#xff0c;存储库&#xff0c;领域服…

(R)-tert-Bu4-DOTAGA,817562-90-6,(R)-DOTAGA-四叔丁酯,的反应特点及性质研究

​ 规格单位&#xff1a;g |货期&#xff1a;按​照具体的库存进行提供 | 纯度&#xff1a;95% 试剂描述&#xff1a; (R)-tert-Bu4-DOTAGA大环化合物是一种多齿配体&#xff0c;其配位原子位于环的骨架上&#xff0c;大环的配位原子可以是O、N、S、Se、P、As等。有二维的…

C++primer(第五版)第七章(类)

类的基本思想是数据抽象和封装. 数据抽象是一种依赖于接口和实现的分离的编程技术. 封装实现了类的接口和实现的分离. 7.1定义抽象数据类型 定义一个抽象数据类型使用关键字struct或是clas(差别仅在于默认访问权限修饰符). //这是一个简单的类定义 class Student{ …

C++ 结合 opencv读取图片与视频

C 结合 opencv读取图片与视频 文章目录 C 结合 opencv读取图片与视频一、安装opencv二 、配置文件准备2.1 新建立文件夹2.2 .vscode文件下配置文件&#xff08;1&#xff09;配置tasks.json文件&#xff08;1&#xff09;配置launch.json 三 、src文件下代码编写3.1 图片的读取…

matplotlib设置坐标轴为象限模式

import numpy as np import matplotlib.pyplot as pltx np.linspace(-np.pi, np.pi, 1000) cosy np.cos(x) siny np.sin(x)plt.xlim(min(x), max(x)) plt.ylim(min(cosy), max(cosy)0.5) plt.plot(x, cosy) plt.plot(x, siny) # 设置坐标刻度 plt.xticks([-np.pi, -np.pi/2,…

ubuntu安装python

ubuntu安装python 安装包下载 切换到想要的文件夹&#xff1a;如 cd /usr/local/python3 下载安装包 wget https://www.python.org/ftp/python/3.8.10/Python-3.8.10.tgz 网速慢的话也可以现在本电脑下载tgz文件&#xff0c;然后上传到服务器 第一次上传失败&#xff01; Py…

SFP3012A-ASEMI代理海矽美快恢复二极管SFP3012A

编辑&#xff1a;ll SFP3012A-ASEMI代理海矽美快恢复二极管SFP3012A 型号&#xff1a;SFP3012A 品牌&#xff1a;MHCHXM&#xff08;海矽美&#xff09; 芯片个数&#xff1a;单芯片 封装&#xff1a;TO-247 恢复时间&#xff1a;≤75ns 工作温度&#xff1a;-40C~175C …

JS中的异步与Promise使用

同步与异步 我们知道JS是一个单线程的语言&#xff0c;即在同一时间只能做一件事情。为什么设计为当线程呢。&#xff1f;在早期JS是为了在浏览器中运行&#xff0c;我们可以利用JS来制作一些页面的效果也可以和用户做一些交互。所以设计为单线程也是为了避免复杂度。比如在网…

常见面试题之线程中并发锁(一)

1. 讲一下synchronized关键字的底层原理&#xff1f; 1.1. 基本使用 如下抢票的代码&#xff0c;如果不加锁&#xff0c;就会出现超卖或者一张票卖给多个人 Synchronized【对象锁】采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】&#xff0c;其它线程再想获取这…

常州工学院计算机组成原理(样卷)

微程序控制器&#xff1a;仿照程序设计的基本方法&#xff0c;将实现指令系统中所有指令所需要的所有控制信号按照一定的规则编码成微指令&#xff0c;若干条实现同一条指令功能的微指令构成一段微程序&#xff0c;将实现所有指令的微程序存放在一个只读存储器ROM中&#xff0c…

一套A股量化系统

shares A 股量化交易系统后台开发语言 Go/Python gmsec算法使用&#xff1a;pytorch全链路量化&#xff0c;行业板块分析&#xff0c;直接贴图。欢迎体验

【计算机视觉】最新综述:南洋理工和上海AI Lab提出基于Transformer的视觉分割综述

文章目录 一、导读二、摘要三、内容解读3.1 研究动机3.2 这篇综述的特色&#xff0c;以及与以往的Transformer综述有什么区别&#xff1f;3.3 Transformer-Based 分割和检测方法总结与对比3.4 相关研究领域的方法总结与对比3.5 不同方法的实验结果对比3.6 未来可以进行的方向 一…

vue三种方式导出报表至excel

1、序言 1.1、源码 源码在下方&#xff0c;复制运行&#xff0c;安装相应的插件即可 1.2、坑 方式一、方式二安装相同插件&#xff1a; npm install xlsx xlsx-style file-saver 导入 xlsx-style 会报如下的错误 解决办法&#xff1a; &#xff08;1&#xff09;去node_modules…

多元回归预测 | Matlab基于灰狼算法(GWO)优化混合核极限学习机HKELM回归预测, GWO-HKELM数据回归预测,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab基于灰狼算法(GWO)优化混合核极限学习机HKELM回归预测, GWO-HKELM数据回归预测,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 …

基于matlab使用深度学习估计身体姿势(附源码)

一、前言 此示例演示如何使用 OpenPose 算法和预训练网络估计一个或多个人的身体姿势。 身体姿势估计的目标是识别图像中人的位置及其身体部位的方向。当场景中存在多个人时&#xff0c;由于遮挡、身体接触和相似身体部位的接近&#xff0c;姿势估计可能会更加困难。 有两种…

【手撕算法|动态规划系列No.1】leetcode1137. 第 N 个泰波那契数

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

【C/C++】数组指针:array 地址 array *parray 两次解引用 **parray 值相同的原因解析

一、提出问题 #include <stdio.h>int main() { char array[16] {A, B}; char (*parray)[16] &array; printf("\n");printf(" array: \t%#lx\n", array); printf("& array: \t%#lx\n", &array); printf("…

SQL server 2012 配置数据库邮件实现邮件发送

日常开发中经常遇到邮件推送场景&#xff0c;我们可以利用SQL server也可以实现邮件发送功能。 一、配置邮件服务器 然后再弹出的页面中选择下一步 输入配置文件名&#xff0c;并添加新用户 在弹出的页面配置邮件服务器的地址、用户名、密码等相关信息 以上信息完成&#xff0…

树莓派 Raspberry Pi Zero 2W 安装默认系统时 ssh 登录并开启摄像头推流一段时间B

Raspberry Pi Zero 2W有点鸡肋&#xff0c;hdmi口用的microhdmi口&#xff0c;不是树莓派4b的minihdmi口&#xff0c;然后zero 2W也没有usb接口&#xff0c;有一个microusb安卓的otg接口&#xff0c;很烦&#xff0c;还好有wifi蓝牙模块&#xff0c;这样子还能ssh&#xff0c;不…