Java 中的泛型(超全详解)

一、泛型概述

1. 什么是泛型?为什么要使用泛型?

泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参列表,普通方法的形参列表中,每个形参的数据类型是确定的,而变量是一个参数。在调用普通方法时需要传入对应形参数据类型的变量(实参),若传入的实参与形参定义的数据类型不匹配,则会报错

参数化类型是什么?以方法的定义为例,在方法定义时,将方法签名中的形参的数据类型也设置为参数(也可称之为类型参数),在调用该方法时再从外部传入一个具体的数据类型和变量。

泛型的本质是为了将类型参数化, 也就是说在泛型使用过程中,数据类型被设置为一个参数,在使用时再从外部传入一个数据类型;而一旦传入了具体的数据类型后,传入变量(实参)的数据类型如果不匹配,编译器就会直接报错。这种参数化类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

//没有泛型的时候,集合如何存储数据
//结论:
//如果我们没有给集合指定类型,默认认为所有的数据类型都是Object类型
//此时可以往集合添加任意的数据类型。
//带来一个坏处:我们在获取数据的时候,无法使用他的特有行为。

//此时推出了泛型,可以在添加数据的时候就把类型进行统一。
//而且我们在获取数据的时候,也省的强转了,非常的方便。

2. 泛型使用场景

在 ArrayList 集合中,可以放入所有类型的对象,假设现在需要一个只存储了 String 类型对象的 ArrayList 集合。

public class demo1 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        for(String s:list){
            System.out.println(s);
        }
    }
}
  • 上面代码没有任何问题,在遍历 ArrayList 集合时,只需将 Object 对象进行向下转型成 String 类型即可得到 String 类型对象。

但如果在添加 String 对象时,不小心添加了一个 Integer 对象,会发生什么?看下面代码:

 public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add(666);

        for (int i = 0; i < list.size(); i++) {
            System.out.println((String)list.get(i));
        }
    }

  • 上述代码在编译时没有报错,但在运行时却抛出了一个 ClassCastException 异常,其原因是 Integer 对象不能强转为 String 类型。

那如何可以避免上述异常的出现?即我们希望当我们向集合中添加了不符合类型要求的对象时,编译器能直接给我们报错,而不是在程序运行后才产生异常。这个时候便可以使用泛型了。

使用泛型代码如下:

 public static void main(String[] args) {
        ArrayList<String> list = new ArrayList();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        //list.add(666);// 在编译阶段,编译器会报错
        
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
  • < String > 是一个泛型,其限制了 ArrayList 集合中存放对象的数据类型只能是 String,当添加一个非 String 对象时,编译器会直接报错。这样,我们便解决了上面产生的 ClassCastException 异常的问题(这样体现了泛型的类型安全检测机制)。

3.总结

泛型的出现就是为了统一集合当中数据类型的

二、泛型类

泛型类的定义

  • 尖括号 <> 中的 泛型标识被称作是类型参数,用于指代任何数据类型。

  • 泛型标识是任意设置的(如果你想可以设置为 Hello都行),Java 常见的泛型标识以及其代表含义如下:

  T :代表一般的任何类。
  E :代表 Element 元素的意思,或者 Exception 异常的意思。
  K :代表 Key 的意思。
  V :代表 Value 的意思,通常与 K 一起配合使用。
  S :代表 Subtype 的意思,文章后面部分会讲解示意。

 自己实现集合

代码如下:

package fangxing;

import java.util.Arrays;

public class MyArrayList<E> {
    Object[] obj = new Object[10];
    int size = 0;

    /*
    E: 表示不确定的类型,该类型在类名后面已经定义过了
    e: 形参的名字,变量名
     */
    public boolean add(E e) {
        obj[size++] = e;
        return true;
        //当添加成功以后,集合还是会把这些数据当做Object类型处理
    }

    public E get(int index) {
        return (E) obj[index];
        //获取的时候集合在把他强转<E>类型

    }

    @Override
    public String toString() {
           return Arrays.toString(obj);

    }
}
package fangxing;

import javax.xml.stream.events.StartDocument;

public class demo3 {
    public static void main(String[] args) {
        MyArrayList<String> list = new MyArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        System.out.println(list);
    }
}

三、泛型方法

格式

package fangxing;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ListUtil {
    private ListUtil() {
    }

    /*
    参数一:集合
    参数二: 最后要添加的元素
     */
    public static <E> void addAll(ArrayList<E> list, E e1, E e2) {
        list.add(e1);
        list.add(e2);
    }

}

package fangxing;

import java.util.ArrayList;

public class demo4 {
    public static void main(String[] args) {
        ArrayList<String>list=new ArrayList<>();
        ListUtil.addAll(list,"zhangsan","lisi");
        System.out.println(list);//[zhangsan, lisi]

    }
}

添加很多元素

public static <E> void addAll(ArrayList<E> list, E ...e1) {
        for (E e : e1) {
          list.add(e);
        }

四、泛型接口

方法1:实现类给出具体类型

举例:

public class MyArrayList2  implements List<String> 
public static void main(String[] args) {
        MyArrayList2 list2=new MyArrayList2();
    }

方法2: 实现类延续泛型,创建对象再确定

public class MyArrayList3 <E>  implements List<E>
  MyArrayList3<String> list = new MyArrayList3<>();

五、类型擦除

1. 什么是类型擦除


泛型的本质是将数据类型参数化,它通过擦除的方式来实现,即编译器会在编译期间擦除代码中的所有泛型语法并相应的做出一些类型转换动作。

换而言之,泛型信息只存在于代码编译阶段,在代码编译结束后,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。也就是说,成功编译过后的 class 文件中不包含任何泛型信息,泛型信息不会进入到运行时阶段。

其实Java中的泛型本质是伪泛型

当把集合定义为string类型的时候,当数据添加在集合当中的时候,仅仅在门口检查了一下数据是否符合String类型,  如果是String类型,就添加成功,当添加成功以后,集合还是会把这些数据当做Object类型处理,当往外获取的时候,集合在把他强转String类型

 当代码编译到class文件的时候,泛型就消失,叫泛型的擦除

看一个例子,假如我们给 ArrayList 集合传入两种不同的数据类型,并比较它们的类信息。

public class GenericType {
    public static void main(String[] args) {  
        ArrayList<String> arrayString = new ArrayList<String>();   
        ArrayList<Integer> arrayInteger = new ArrayList<Integer>();   
        System.out.println(arrayString.getClass() == arrayInteger.getClass());// true
    }  
}

在这个例子中,我们定义了两个 ArrayList 集合,不过一个是 ArrayList< String>,只能存储字符串。一个是 ArrayList< Integer>,只能存储整型对象。我们通过 arrayString 对象和 arrayInteger 对象的 getClass() 方法获取它们的类信息并比较,发现结果为true。

明明我们在 <> 中传入了两种不同的数据类型,那为什么它们的类信息还是相同呢? 这是因为,在编译期间,所有的泛型信息都会被擦除, ArrayList< Integer > 和 ArrayList< String >类型,在编译后都会变成ArrayList< Objec t>类型。

那么是不是所有的类型参数被擦除后都以 Object 类进行替换呢?

  • 答案是否定的,大部分情况下,类型参数 T 被擦除后都会以 Object 类进行替换;而有一种情况则不是,那就是使用到了 extends 和 super 语法的有界类型参数(即泛型通配符,后面我们会详细解释 

2. 类型擦除的原理

假如我们定义了一个 ArrayList< Integer > 泛型集合,若向该集合中插入 String 类型的对象,不需要运行程序,编译器就会直接报错。这里可能有小伙伴就产生了疑问:

不是说泛型信息在编译的时候就会被擦除掉吗?那既然泛型信息被擦除了,如何保证我们在集合中只添加指定的数据类型的对象呢?

换而言之,我们虽然定义了 ArrayList< Integer > 泛型集合,但其泛型信息最终被擦除后就变成了 ArrayList< Object > 集合,那为什么不允许向其中插入 String 对象呢?

Java 是如何解决这个问题的?

其实在创建一个泛型类的对象时, Java 编译器是先检查代码中传入 < T > 的数据类型,并记录下来,然后再对代码进行编译,编译的同时进行类型擦除;如果需要对被擦除了泛型信息的对象进行操作,编译器会自动将对象进行类型转换。

可以把泛型的类型安全检查机制和类型擦除想象成演唱会的验票机制:以 ArrayList< Integer> 泛型集合为例。

当我们在创建一个 ArrayList< Integer > 泛型集合的时候,ArrayList 可以看作是演唱会场馆,而< T >就是场馆的验票系统,Integer 是验票系统设置的门票类型;
当验票系统设置好为< Integer >后,只有持有 Integer 门票的人才可以通过验票系统,进入演唱会场馆(集合)中;若是未持有 Integer 门票的人想进场,则验票系统会发出警告(编译器报错)。
在通过验票系统时,门票会被收掉(类型擦除),但场馆后台(JVM)会记录下观众信息(泛型信息)。
进场后的观众变成了没有门票的普通人(原始数据类型)。但是,在需要查看观众的信息时(操作对象),场馆后台可以找到记录的观众信息(编译器会自动将对象进行类型转换)

 

举例如下:

public class GenericType {
    public static void main(String[] args) {  
        ArrayList<Integer> arrayInteger = new ArrayList<Integer>();// 设置验票系统   
        arrayInteger.add(111);// 观众进场,验票系统验票,门票会被收走(类型擦除)
        Integer n = arrayInteger.get(0);// 获取观众信息,编译器会进行强制类型转换
        System.out.println(n);
    }  
}

擦除 ArrayList< Integer > 的泛型信息后,get() 方法的返回值将返回 Object 类型,但编译器会自动插入 Integer 的强制类型转换。也就是说,编译器把 get() 方法调用翻译为两条字节码指令:

对原始方法 get() 的调用,返回的是 Object 类型;
将返回的 Object 类型强制转换为 Integer 类型;

代码如下:

	Integer n = arrayInteger.get(0);// 这条代码底层如下:
	
	//(1)get() 方法的返回值返回的是 Object 类型
	Object object = arrayInteger.get(0);
	//(2)编译器自动插入 Integer 的强制类型转换
	Integer n = (Integer) object;

3. 类型擦除小结


1.泛型信息(包括泛型类、接口、方法)只在代码编译阶段存在,在代码成功编译后,其内的所有泛型信息都会被擦除,并且类型参数 T 会被统一替换为其原始类型(默认是 Object 类,若有 extends 或者 super 则另外分析);

2.在泛型信息被擦除后,若还需要使用到对象相关的泛型信息,编译器底层会自动进行类型转换(从原始类型转换为未擦除前的数据类型)。

六、泛型通配符

1. 泛型的继承

泛型不具备继承性,但是数据具备继承性

  此时,泛型里面写的什么类型,那么就传递什么类型的数据

泛型不具备继承性举例

package fangxing;

import java.util.ArrayList;

public class demo5 {
    public static void main(String[] args) {
        /*
        泛型不具备继承性,但是数据具备继承性
         */
        ArrayList<Ye> list1=new ArrayList<>();
        ArrayList<Fu> list2=new ArrayList<>();
        ArrayList<Zi> list3=new ArrayList<>();
        //调用method方法
        method(list1);
        //method(list2);//编译错误
//method(list3);//编译错误
    }
    /*
    此时,泛型里面写的什么类型,那么就传递什么类型的数据
     */
    public static  void method(ArrayList<Ye> list){

    }
}

class Ye{

}
class Fu extends Ye{

}
class Zi extends Fu{

}

数据具备继承性 

   //数据具备继承性
        list1.add(new Ye());//添加爷爷的对象等
        list1.add(new Fu());
        list1.add(new Zi());
定义一个方法,形参是一个集合,但是集合中的数据类型不确定。
应用场景:
*      1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。
*      2.如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符
* 泛型的通配符:
*      关键点:可以限定类型的范围。
/*
 * 此时,泛型里面写的是什么类型,那么只能传递什么类型的数据。
 * 弊端:
 *      利用泛型方法有一个小弊端,此时他可以接受任意的数据类型
 *      Ye  Fu   Zi    Student
 *
 * 希望:本方法虽然不确定类型,但是以后我希望只能传递Ye Fu Zi
 *
 * 此时我们就可以使用泛型的通配符:
 *      ?也表示不确定的类型
 *      他可以进行类型的限定
 *      ? extends E: 表示可以传递E或者E所有的子类类型
 *      ? super E:表示可以传递E或者E所有的父类类型
 *

举例

package fangxing;

import java.util.ArrayList;

/*
 *   需求:
 *       定义一个方法,形参是一个集合,但是集合中的数据类型不确定。
 *
 * */
/*
 * 此时,泛型里面写的是什么类型,那么只能传递什么类型的数据。
 * 弊端:
 *      利用泛型方法有一个小弊端,此时他可以接受任意的数据类型
 *      Ye  Fu   Zi    Student
 *
 * 希望:本方法虽然不确定类型,但是以后我希望只能传递Ye Fu Zi
 *
 * 此时我们就可以使用泛型的通配符:
 *      ?也表示不确定的类型
 *      他可以进行类型的限定
 *      ? extends E: 表示可以传递E或者E所有的子类类型
 *      ? super E:表示可以传递E或者E所有的父类类型
 *
 * 应用场景:
 *      1.如果我们在定义类、方法、接口的时候,如果类型不确定,就可以定义泛型类、泛型方法、泛型接口。
 *      2.如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以泛型的通配符
 * 泛型的通配符:
 *      关键点:可以限定类型的范围。
 *
 * */
public class demo6 {
    public static void main(String[] args) {

        //创建集合的对象
        ArrayList<Ye> list1 = new ArrayList<>();
        ArrayList<Fu> list2 = new ArrayList<>();
        ArrayList<Zi> list3 = new ArrayList<>();

        ArrayList<Student2> list4 = new ArrayList<>();

        method(list1);
        method(list2);
        //method(list3);


        //method(list4);
    }
    public static void method(ArrayList<? super Fu> list) {

    }
}
class Ye {
}

class Fu extends Ye {
}

class Zi extends Fu {
}

class Student2{}

2.练习

/*
      需求:
          定义一个继承结构:
                              动物
                   |                           |
                   猫                          狗
                |      |                    |      |
             波斯猫   狸花猫                泰迪   哈士奇
           属性:名字,年龄
           行为:吃东西
                 波斯猫方法体打印:一只叫做XXX的,X岁的波斯猫,正在吃小饼干
                 狸花猫方法体打印:一只叫做XXX的,X岁的狸花猫,正在吃鱼
                 泰迪方法体打印:一只叫做XXX的,X岁的泰迪,正在吃骨头,边吃边蹭
                 哈士奇方法体打印:一只叫做XXX的,X岁的哈士奇,正在吃骨头,边吃边拆家

      测试类中定义一个方法用于饲养动物
          public static void keepPet(ArrayList<???> list){
              //遍历集合,调用动物的eat方法
          }
      要求1:该方法能养所有品种的猫,但是不能养狗
      要求2:该方法能养所有品种的狗,但是不能养猫
      要求3:该方法能养所有的动物,但是不能传递其他类型
   */

测试类

package lx;

import java.util.ArrayList;

public class demo1 {
    /*
          需求:
              定义一个继承结构:
                                  动物
                       |                           |
                       猫                          狗
                    |      |                    |      |
                 波斯猫   狸花猫                泰迪   哈士奇
               属性:名字,年龄
               行为:吃东西
                     波斯猫方法体打印:一只叫做XXX的,X岁的波斯猫,正在吃小饼干
                     狸花猫方法体打印:一只叫做XXX的,X岁的狸花猫,正在吃鱼
                     泰迪方法体打印:一只叫做XXX的,X岁的泰迪,正在吃骨头,边吃边蹭
                     哈士奇方法体打印:一只叫做XXX的,X岁的哈士奇,正在吃骨头,边吃边拆家

          测试类中定义一个方法用于饲养动物
              public static void keepPet(ArrayList<???> list){
                  //遍历集合,调用动物的eat方法
              }
          要求1:该方法能养所有品种的猫,但是不能养狗
          要求2:该方法能养所有品种的狗,但是不能养猫
          要求3:该方法能养所有的动物,但是不能传递其他类型
       */
    public static void main(String[] args) {
        HuskyDog h = new HuskyDog("哈士奇", 1);
        LihuaCat l = new LihuaCat("狸花猫", 2);
        PersianCat p = new PersianCat("波斯猫", 3);
        TeddyDog t = new TeddyDog("泰迪", 4);
        ArrayList<LihuaCat> list1 = new ArrayList<>();
        ArrayList<PersianCat> list2 = new ArrayList<>();
        // 向列表中添加一些猫的实例
        list1.add(l);
        list2.add(p);
        //调用方法
        keepPet1(list1);
        keepPet1(list2);
        System.out.println("-------------------------------------------");
        ArrayList<HuskyDog> list3 = new ArrayList<>();
        ArrayList<TeddyDog> list4 = new ArrayList<>();
        // 向列表中添加一些狗的实例
        list3.add(h);
        list4.add(t);
        //调用方法
        keepPet2(list3);
        keepPet2(list4);
        System.out.println("-------------------------------------------");
        list1.add(l);
        list2.add(p);
        list3.add(h);
        list4.add(t);
        keepPet3(list1);
        keepPet3(list2);
        keepPet3(list3);
        keepPet3(list4);
    }


    /*
    此时我们就可以使用泛型的通配符:
      ?也表示不确定的类型
      他可以进行类型的限定
      ? extends E: 表示可以传递E或者E所有的子类类型
     ? super E:表示可以传递E或者E所有的父类类型
     */
    //  要求1:该方法能养所有品种的猫,但是不能养狗
    public static void keepPet1(ArrayList<? extends Cat> list) {
        //遍历集合,调用动物的eat方法
        for (Cat cat : list) {
            cat.eat();
        }
    }
    //  要求2:该方法能养所有品种的狗,但是不能养猫
    public static void keepPet2(ArrayList<? extends Dog> list) {
        //遍历集合,调用动物的eat方法
        for (Dog dog : list) {
            dog.eat();
        }
    }

    //  要求3:该方法能养所有的动物,但是不能传递其他类型
    public static void keepPet3(ArrayList<? extends Animal> list) {
        //遍历集合,调用动物的eat方法
        for (Animal animal : list) {
            animal.eat();
        }
    }
}

Animal类

package lx;

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Animal{name = " + name + ", age = " + age + "}";
    }
    public abstract  void eat();
}

cat类型

package lx;

public abstract class Cat extends Animal{

    public Cat() {
    }

    public Cat(String name, int age) {
        super(name, age);
    }
}

Dog类

package lx;

public abstract class Dog extends Animal{
    public Dog() {
    }

    public Dog(String name, int age) {
        super(name, age);
    }
}

哈士奇类

package lx;

public class HuskyDog extends Dog{
    @Override
    public void eat() {
        System.out.println("一只叫做"+getName()+"的,"+getAge()+"岁的哈士奇,正在吃骨头,边吃边拆家");

    }

    public HuskyDog() {
    }

    public HuskyDog(String name, int age) {
        super(name, age);
    }
}

狸花猫类

package lx;

public class LihuaCat extends Cat {
    @Override
    public void eat() {
        System.out.println("一只叫做" + getName() + "的," + getAge() + "岁的狸花猫,正在吃鱼");
    }

    public LihuaCat() {
    }

    public LihuaCat(String name, int age) {
        super(name, age);
    }
}

波斯猫类

package lx;

public class PersianCat extends Cat{
    @Override
    public void eat() {
        System.out.println("一只叫做"+getName()+"的,"+getAge()+"岁的波斯猫,正在吃小饼干");
    }

    public PersianCat() {
    }

    public PersianCat(String name, int age) {
        super(name, age);
    }
}

泰迪猫类

package lx;

public class TeddyDog extends Dog{
    @Override
    public void eat() {
        System.out.println("一只叫做"+getName()+"的,"+getAge()+"岁泰迪,正在吃骨头,边吃边蹭");
    }

    public TeddyDog() {
    }

    public TeddyDog(String name, int age) {
        super(name, age);
    }
}

总结

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VS2022 git拉取/推送代码错误

第一步&#xff1a;打开VS2022 第二步&#xff1a;工具->选项->源代码管理->Git 全局设置 第三步&#xff1a;加密网络提供程序设置为&#xff1a;OpenSSL 完结&#xff1a;

函数式接口、匿名内部类、lambda表达式

一、函数式接口 只有一个抽象方法的接口叫函数式接口&#xff0c;不能有两个&#xff0c;也不能有方法实现。 FunctionalInterface注解标记&#xff0c;在idea中可以用这个注解验证是不是函数式接口。实现函数式接口可以转成lambda表达式。 二、匿名内部类 匿名内部类的格式&a…

Java面试八股之Redis单线程为什么性能高

Redis单线程为什么性能高 1.内存数据库特性 要点&#xff1a;Redis是一个内存数据库&#xff0c;其数据主要存储在内存中&#xff0c;而非磁盘。内存访问的速度远超磁盘&#xff0c;通常可达纳秒级别&#xff0c;这使得Redis在处理数据时几乎不受I/O瓶颈的影响。由于数据操作…

Python31 自然语言处理NLP之NLTK的使用

1.关于自然语言处理NLP 自然语言处理NLP是人工智能和计算机科学的一个子领域&#xff0c;专注于计算机与人类&#xff08;自然&#xff09;语言之间的互动。其目的是使计算机能够理解、解释和生成人类语言。NLP 涉及语言学、计算机科学和人工智能的多学科交叉&#xff0c;通过…

SAP与税控系统集成案例

一、项目背景 重庆润通控股有限公司成立于2007年&#xff0c;是一家集合汽柴油动力及终端、摩托车、储能电源、汽车零部件、金融服务等产业的多元化集团公司。 大量订单数据导致订单业务会很复杂&#xff0c;为提供订单完成质量&#xff0c;引入税控系统服务商进行订单开票…

实战精选 | 如何在一台 Linux AI PC 上高效运行 OpenVINO™

点击蓝字 关注我们 作者&#xff1a;Adrian Boguszewski&#xff0c;英特尔 AI 软件布道师 武卓博士&#xff0c;英特尔 AI 软件布道师 什么是 AI PC&#xff0c;为什么它有一个特殊的名字&#xff1f; AI PC 是时下 PC 领域的一个热门话题。与普通 PC 不同&#xff0c;AI PC 配…

linux 0.11 中的重要的全局变量

通过对全局变量的了解&#xff0c;也有助于了解整个代码的逻辑。就跟学习类一样&#xff0c;了解类有哪些成员变量&#xff0c;也有助于了解类的成员函数的功能。 &#xff08;1&#xff09;内存初始化相关 static u_char mem_map [ PAGING_PAGES ] { 0 , } .本数组对 1M 以外…

JavaSE 面向对象程序设计进阶 IO 练习读取多个对象

练习读取多个对象 用序列化流将对象写入文件 import java.io.*; import java.nio.charset.Charset;public class Main {public static void main(String[] args) throws IOException, ClassNotFoundException {//序列化多个对象Person p1new Person("多多", 男,20)…

动手学深度学习(Pytorch版)代码实践 -循环神经网络-57长短期记忆网络(LSTM)

57长短期记忆网络&#xff08;LSTM&#xff09; 1.LSTM原理 LSTM是专为解决标准RNN的长时依赖问题而设计的。标准RNN在训练过程中&#xff0c;随着时间步的增加&#xff0c;梯度可能会消失或爆炸&#xff0c;导致模型难以学习和记忆长时间间隔的信息。LSTM通过引入一组称为门…

55070-001J 同轴连接器

型号简介 55070-001J是Southwest Microwave的连接器。这款连接器外壳和中心接触件采用 BeCu 合金制成&#xff0c;这是一种具有良好导电性和机械性能的铜合金。绝缘珠则使用了 PEEK HT 材料制成&#xff0c;这是一种耐高温、耐化学腐蚀的工程塑料。为了确保连接的可靠性和稳定性…

旷野之间11 - 开源 SORA 已问世!训练您自己的 SORA 模型!

​​​​​ 目前最接近 SORA 的开源模型是 Latte,它采用了与 SORA 相同的 Vision Transformer 架构。Vision Transformer 究竟有何独特之处?它与之前的方法有何不同? Latte 尚未开源其文本转视频训练代码。我们复制了论文中的文本转视频训练代码,并将其提供给任何人使用,…

袋鼠云产品支持全栈信创适配,更加安全可靠、自主可控

随着国产替换的深化&#xff0c;企业对信创产品的需求逐渐融合更丰富的业务诉求以及未来数智规划&#xff0c;正从“同类替换”转向“迭代升级”。 当前&#xff0c;袋鼠云的产品与芯片、服务器、数据库、操作系统、中间件、云平台等主流信创厂商全面兼容适配&#xff0c;为企…

3.相机标定原理及代码实现(opencv)

1.相机标定原理 相机参数的确定过程就叫做相机标定。 1.1 四大坐标系及关系 &#xff08;1&#xff09;像素坐标系&#xff08;单位&#xff1a;像素&#xff08;pixel&#xff09;&#xff09; 像素坐标系是指相机拍到的图片的坐标系&#xff0c;以图片的左上角为坐标原点&a…

工厂人员定位系统介绍及解决方案

着现代工业不断发展&#xff0c;工厂人员定位系统已经广泛的用于各个大型工厂&#xff0c;这主要是因为UWB人员定位系统功能性非常强大&#xff0c;发挥着更加全面的功能优势&#xff0c;满足了不同厂区对工作环境的管理。而它的出现&#xff0c;将人员定位系统达到了更加精准的…

CISCN2024 RE 后两道 wp 复现

5. gdb_debug 其实逻辑还是挺简单的&#xff0c;当时没认真做 伪代码还算清晰 几个循环的加密之后判断密文 难点是前面有随机数参与加密&#xff0c;不过可以猜测随机数是不变的。 第一段加密 flag异或一组随机数&#xff0c;这里可以在异或的位置下条件断点&#xff0c;用…

windows信息收集和提权

目录 手动收集 工具收集 windows本地内核提权 本地提权 根据windows去找需要的exp进行利用 提权后结合mimikatz使用 msf提权 简单提权 生成后门 上线 BypassUAC绕过UAC提权 msf带的bypassuac模块可以尝试提权 Bypassuac提权命令操作 提权成功 ​local_exploi…

【python】随机森林预测汽车销售

目录 引言 1. 数据收集与预处理 2. 划分数据集 3. 构建随机森林模型 4. 模型训练 5. 模型评估 6. 模型调优 数据集 代码及结果 独热编码 随机森林模型训练 特征重要性图 混淆矩阵 ROC曲线 引言 随机森林&#xff08;Random Forest&#xff09;是一种集成学习方法…

全网最炸裂的5款SD涩涩模型!身体真的是越来越不好了!建议收藏,晚上自己偷偷打开看!

很多人说&#xff0c;**自从学了SD后&#xff0c;身体一天不如一天了。**今天就再接再厉&#xff0c;给大家推荐5个涩涩的模型。 【身材调节器】 顾名思义&#xff0c;这个lora可以帮你在出图时凹出想要的S型曲线。出图效果的大小由lora的权重来设定&#xff0c;权重越小越贫穷…

本地开发微信小程序,使用巴比达内网穿透

在微信小程序开发的热潮中&#xff0c;开发者常面临的一个挑战是如何在复杂的网络环境下测试和调试内网环境中的服务。巴比达正为这一难题提供了一条解决方案&#xff0c;极大简化了微信小程序与内网服务器之间通信的流程&#xff0c;加速了开发迭代周期。 以往&#xff0c;开…

3D渲染模型是白色的?问题出在以下6点,教你快速解决!

你的3D模型渲染出来是不是黑色、白色、粉色或者扭曲的&#xff1f; 出现这种情况很有可能是你的贴图纹理丢失或损坏&#xff01; 幸运的是&#xff0c;有一些常见的方法可以解决此问题并恢复纹理。在本文中&#xff0c;小编将分享如何排查和解决不同方案下的纹理问题。通常问…