数据结构初阶(1)(一些学习数据结构所需掌握的先导知识:包装类、装箱与拆箱、泛型【泛型的编译——擦除机制、泛型的上界、泛型方法、裸类型】、List简介)

news2024/11/22 22:36:26

目录

包装类

基本数据类型(Primitive Types):

包装类(Wrapper Classes):

装箱和拆箱

自动装箱和自动拆箱

泛型

泛型的编译——很重要的擦除机制:

泛型的上界:

泛型方法:

裸类型

List


包装类

基本数据类型和包装类是Java中处理数据的两种不同方式。

基本数据类型(Primitive Types):

Java的基本数据类型是直接存储数据的原始类型,包括以下8种类型:

byte:1字节,用于表示整数
short:2字节,用于表示整数
int:4字节,用于表示整数
long:8字节,用于表示长整数
float:4字节,用于表示单精度浮点数
double:8字节,用于表示双精度浮点数
char:2字节,用于表示字符
boolean:1位,用于表示布尔值(true或false)

包装类(Wrapper Classes):

为了方便在基本数据类型和对象之间进行转换,Java提供了对应的包装类。每个基本数据类型都有对应的包装类,命名规则是将首字母大写,例如:

Byte:对应byte
Short:对应short
Integer:对应int
Long:对应long
Float:对应float
Double:对应double
Character:对应char
Boolean:对应boolean


包装类提供了许多有用的方法来处理基本数据类型,例如进行转换、比较、解析等。它们还允许将基本数据类型作为对象使用,在集合类中存储和操作。

基本数据类型和包装类的区别: 

  • 存储方式:基本数据类型直接存储数据值,而包装类是将数据值封装在对象中。
  • 空值表示:基本数据类型没有空值,但包装类可以表示空值通过null。
  • 默认值:基本数据类型有各自的默认值(如0、0.0、false等),而包装类的默认值是null。
  • 内存占用:基本数据类型占用的内存比包装类少,因为基本数据类型直接存储数据值,而包装类需要额外的空间用于存储对象的引用。
  • 包装类提供了许多实用的方法来处理基本数据类型,例如类型转换、数学运算等,而基本数据类型没有这些方法。

在Java中,自动装箱(Autoboxing)和拆箱(Unboxing)机制允许基本数据类型和包装类之间的自动转换。这使得在需要使用对象的情况下可以直接使用基本数据类型,而无需手动进行类型转换。

装箱和拆箱

又称“显示装箱”。

int i = 10;

// 装箱操作,新建一个 Integer 类型对象,将 i 的值放入对象的某个属性中
Integer ii = Integer.valueOf(i);//是手动装箱

Integer ij = new Integer(i);//是手动装箱




// 拆箱操作,将 Integer 对象中的值取出,放到一个基本数据类型中
int j = ii.intValue();

Integer a = new Integer(10);

//显示拆箱 拆箱为自己指定的元素
int c = a.intValue();
System.out.println(c);

double d = a.doubleValue();
System.out.println(d);

自动装箱和自动拆箱

自动装箱,又称“隐式装箱”,是指在编译阶段,Java编译器会自动将基本类型转换为对应的包装类型,而不需要显式地调用构造函数来完成装箱操作。

nt i = 10;
Integer ii = i; // 自动装箱
Integer ij = (Integer)i; // 自动装箱

int j = ii; // 自动拆箱
int k = (int)ii; // 自动拆箱

严格来说,int k = (int)ii; 不是自动装箱,而是强制类型转换,将基本数据类型int转换为包装类型Integer。在这种情况下,需要注意i的值不能超出Integer类型的取值范围,否则会抛出NumberFormatException异常。

易错题:

1、下列代码输出什么,为什么?

public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);
System.out.println(c == d);
}

 private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

 这段代码主要是对Java中自动装箱的缓存机制进行测试。Java中对于byte、short、int类型的自动装箱,如果值在[-128, 127]之间,则会将其缓存起来,重复使用同一个对象。

在这段代码中,首先声明了两个Integer类型的变量a和b,并将它们赋值为127,然后声明了两个Integer类型的变量c和d,并将它们赋值为128。

在输出语句中,通过"=="运算符比较a和b、c和d的值是否相等,如果相等则输出true,否则输出false。

由于a和b的值都在[-128, 127]之间,因此它们会被缓存起来,重复使用同一个对象,所以a和b指向的是同一个对象,因此a==b的结果为true。

而c和d的值都不在[-128, 127]之间,因此它们不会被缓存起来,每次自动装箱时都会创建一个新的Integer对象,所以c和d指向的不同对象,因此c==d的结果为false。

因此,这段代码的输出结果为:
true
false

2、下列在Java语言中关于数据类型和包装类的说法,正确的是()

A.基本(简单)数据类型是包装类的简写形式,可以用包装类替代基本(简单)数据类型

B. long和double都占了64位(64bit)的存储空间。

C.默认的整数数据类型是int,默认的浮点数据类型是float。

D.和包装类一样,基本(简单)数据类型声明的变量中也具有静态方法,用来完成进制转化等

 答案:B

A. 错误。基本数据类型和包装类是不同的。基本数据类型是直接存储数据的原始类型,而包装类是对基本数据类型进行封装的类。虽然在某些情况下,基本数据类型可以自动转换为对应的包装类,但它们并不是同一概念。

C.默认的浮点数据类型是double。

D. 错误。基本数据类型声明的变量不具有静态方法。只有包装类才有静态方法,用于提供一些辅助功能,如进制转换等。基本数据类型的变量只能访问与其对应的基本数据类型的功能和操作,无法调用静态方法。

泛型

在编程中,泛型(Generic)是一种通用的编程概念,它可以用于定义能够适用于多种类型的函数、类或数据结构。泛型允许在编写代码时不指定具体的类型,而是使用类型参数来表示待定的类型。

1. 泛型是将数据类型参数化,进行传递

2. 使用 <T> 表示当前类是一个泛型类。

3. 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换

泛型只能接受类,所有的基本数据类型必须使用包装类!

当编译器可以根据上下文推导出类型实参时,可以省略类型实参的填写:

MyArray<Integer> list = new MyArray<>(); // 可以推导出实例化需要的类型实参为 Integer

泛型的编译——很重要的擦除机制:

泛型的编译中,擦除(Erasure)机制是一项重要的步骤。它是指在编译阶段将泛型类型信息从生成的字节码中擦除的过程。擦除机制是为了保持与Java早期版本的向后兼容性,并允许泛型代码与不使用泛型的代码进行交互。

通过命令:javap -c 查看字节码文件,所有的T都变成了Object。

原来,当使用泛型时,编译器会在编译过程中执行以下操作:

  1. 类型擦除:编译器将泛型类型参数替换为其上界或Object类型。例如,一个泛型类List<T>在擦除后会变成List<Object>。
  2. 类型转换:由于擦除导致类型信息丢失,编译器会插入必要的类型转换操作来保证代码的类型安全性。这些类型转换在编译时进行。
  3. 插入桥方法:当泛型类或接口涉及继承或实现时,编译器会插入桥方法来确保泛型类型的正确转换。桥方法是编译器生成的方法,用于在泛型类型和非泛型类型之间进行桥接。

现在,我们只需要知道:

在编译的过程当中,将所有的T替换为Object这种机制,我们称为:擦除机制。 Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。

这里是一篇有关泛型擦除机制的文章介绍:Java泛型擦除机制之答疑解惑 - 知乎 (zhihu.com)

好了,下面是需要格外注意的一点:

擦除机制导致泛型类型在运行时丢失了具体的类型信息,这就是为什么在运行时无法检测泛型类型的实际参数类型。例如,对于一个List<String>对象,在运行时它只是一个普通的List对象,无法知道其元素类型是String。

数组是很特殊的,不可以整体强制类型转换。

不可以实例化泛型。

public Object[] array = new Object[10];
//public T[] array = new T[10]; 不允许 实例化一个泛型数组
//public T[] array = (T[])new Object[10];//这样写也不好!!

public T[] array = (T[])new Object[10];


 public static void main3(String[] args) {
        //泛型是如何编译的
        MyArray<String> myArray = new MyArray<>();

        myArray.set(0,"hello");

        //String[] ret = (String) myArray.getArray();
        //没意义,已经强制转换过了!本质它是一个 Object数组,
        //啥都能放,你怎么确定放的就是字符串?
        //String[] ret = myArray.getArray();也还是不行
        /*总的来说,就是我们返回的Object数组里面,可能存放的是任何的数据类型,
        可能是String,可能是Person,运行的时候,
        直接转给String类型的数组,编译器认为是不安全的。*/
        Object[] ret = myArray.getArray();
        System.out.println(Arrays.toString(ret));
    }

    public Object[] getArray() {
        return array;
    }


   /* public T[] getArray() {
        return array;
    }*/

    //那我就要有这个方法呢?
    public T[] getArray() {
        return (T[])array;
    }

我们来谈一谈:

  • 为什么不可以这样写:public T[] array = new T[10]; 
  • 为什么这样写也不好?:public T[] array = (T[])new Object[10];
  • 写成这样:public T[] array = (T[])new Object[10];

Java中不允许直接实例化泛型数组的原因与类型擦除机制有关。在泛型的擦除过程中,泛型类型参数被替换为其上界或Object类型,因此在编译时无法确定具体的泛型类型。这就导致无法直接实例化一个泛型数组。

让我们看看为什么以下两种写法都不被允许:

1、public T[] array = new T[10];
这种写法是不被允许的,因为在编译时无法确定泛型类型参数T的具体类型。编译器无法实例化一个未知类型的数组。例如,如果T是一个类的类型参数,那么new T[10]将无法确定要实例化哪个具体类的数组。

2、public T[] array = (T[])new Object[10];
这种写法使用了类型转换将一个Object数组转换为泛型类型数组。尽管编译器允许这种写法,但是需要注意的是,这会引发潜在的运行时类型转换错误。由于类型擦除,编译器无法检查类型转换的正确性,因此可能会导致ClassCastException或其他类型相关的异常。

为了解决这个问题,可以采用以下方式来实例化泛型数组:

public class GenericArray<T> {
    private T[] array;

    public GenericArray(int size) {
        // 使用反射创建泛型数组
        array = (T[]) new Object[size];
    }

    public T[] getArray() {
        return array;
    }

    public static void main(String[] args) {
        GenericArray<String> genericArray = new GenericArray<>(10);
        String[] array = genericArray.getArray();
        System.out.println(Arrays.toString(array));
    }
}

在上述示例中,我们通过使用反射来创建泛型数组。尽管编译器会发出未经检查的警告,但是我们可以安全地使用泛型数组,并在运行时避免类型转换错误。

所以不管怎么样,返回什么,我们都用Object来接收。源码里面也是这么写的。

现在,你可以回答以下两个问题了吗:

1、为什么,T [ ]  ts = new T[5]; 是不对的,编译的时候,替换为Object,不是相当于:Object [ ] ts = new Object[5]吗? 

2、类型擦除,一定是把T变成Object吗?

解析:

1、在Java中,泛型数组的创建是受到限制的。T [ ]  ts = new T[5];这样的语法是不被允许的,因为在泛型的擦除过程中,数组的实际类型信息是丢失的。编译器无法确定如何创建一个泛型数组,因为它无法确定擦除后的具体类型。

为了解释这一点,让我们假设编译器允许这样的语法,并将其替换为Object [ ] ts = new Object[5];然后考虑以下情况:

ts[0] = new T();

这里的问题是,编译器无法确定T的具体类型是什么,因为类型信息已经被擦除了。如果T代表某个类或接口的子类型,那么使用new T()无法确定具体实例化哪个类。

为了避免这种类型不确定性,Java禁止直接创建泛型数组。相反,可以使用通配符类型或者使用Object数组,并进行类型转换来实现类似的效果。

2、类型擦除并不一定将类型参数替换为Object。在泛型的擦除过程中,类型参数被替换为它们的上界(或者如果没有指定上界,则被替换为Object)。(我们马上就要提到“泛型的上界”了)。

例如,对于 List <T>,在类型擦除后会变为 List <Object>。但是,如果我们指定了上界,例如List<T extends Number>,在类型擦除后,T将被替换为Number,而不是Object。

总结起来,类型擦除会将类型参数替换为上界或Object,具体取决于类型参数是否有指定的上界。这样做是为了在擦除后仍然保持代码的类型安全性,并且与不使用泛型的代码进行兼容。

尽管泛型的擦除机制限制了在运行时访问具体的泛型类型信息,但在编译时它仍然提供了类型安全性和编译时类型检查的好处。擦除机制使得泛型代码可以与不使用泛型的旧代码进行交互,并允许在编译时捕获一些类型错误。尽管存在一些局限性,但擦除机制仍然是Java泛型实现的核心特性之一。

泛型的上界:

泛型的上界(Upper Bound)是一种约束,用于限制泛型类型参数的范围。上界指定了一个类型参数必须是某个特定类型或特定类型的子类型。

在Java中,可以使用extends关键字来指定泛型的上界。例如,假设我们有一个泛型类或泛型方法,使用类型参数T。我们可以使用extends关键字来限制T必须是某个特定类或接口的子类型。下面是一个简单的示例:

public class ExampleClass<T extends Number> {
    private T value;
    
    public ExampleClass(T value) {
        this.value = value;
    }
    
    public T getValue() {
        return value;
    }
    
    // 其他方法和逻辑
}

在上面的示例中,类型参数 T 被限制为Number类的子类型。这意味着我们只能在ExampleClass中使用Number及其子类型作为T的具体类型。例如,可以使用Integer、Double或其他继承自Number的类型来实例化ExampleClass。

通过指定上界,我们可以在编写泛型代码时对类型参数进行更精确的控制,并在编译时捕获一些类型错误。这可以提高代码的安全性和可读性,并允许更好地利用静态类型检查的好处。

泛型方法:

泛型方法是指在方法声明中使用了泛型类型参数的方法。泛型方法具有以下两种类型:

可类型推导的泛型方法(Generic Method with Type Inference):这种泛型方法可以根据方法参数的类型推导出泛型类型参数的具体类型,而不需要显式地指定类型参数。编译器能够根据方法调用时提供的参数类型来推断泛型类型参数。这种类型的泛型方法可以更简洁地调用,因为编译器会自动推断类型。
以下是一个可类型推导的泛型方法的示例:

public <T> void printArray(T[] array) {
    for (T element : array) {
        System.out.println(element);
    }
}

在上面的示例中,泛型类型参数T并没有显式地指定类型,而是根据方法参数array的类型进行推导。例如,如果调用printArray(new Integer[]{1, 2, 3}),编译器会自动推断T为Integer类型。

不可类型推导的泛型方法(Generic Method without Type Inference):这种泛型方法在方法调用时需要显式地指定泛型类型参数的具体类型。无法根据方法参数的类型自动推断类型参数。需要手动指定泛型类型参数,这在某些情况下可能是必需的,特别是当类型推断无法正常工作或需要显式控制类型时。
以下是一个不可类型推导的泛型方法的示例:

public <T> void printArray(T[] array, Class<T> type) {
    for (T element : array) {
        System.out.println(element);
    }
}

在上面的示例中,我们需要在方法调用时显式地指定泛型类型参数T的具体类型,例如printArray(new Integer[]{1, 2, 3}, Integer.class)。

总而言之,可类型推导的泛型方法允许编译器根据方法参数的类型自动推断泛型类型参数,而不可类型推导的泛型方法需要显式地指定泛型类型参数的具体类型。可类型推导的泛型方法通常更简洁易用,但在某些情况下不可类型推导的泛型方法是必需的。

裸类型

裸类型(Raw Type)是指在泛型代码中使用泛型类型参数而没有指定具体类型实参的情况。当使用裸类型时,泛型的类型安全性检查被绕过,可能导致编译器无法捕获潜在的类型错误。

裸类型主要出现在以下两种情况下:

  • 在旧版本的Java代码中:在引入泛型之前的旧代码中,没有使用泛型的概念。当将这些代码与使用泛型的新代码进行交互时,编译器会发出未经检查的警告,并将泛型类型参数擦除为裸类型。
  • 显式使用裸类型:在泛型代码中,可以显式地指定裸类型,即省略泛型的具体类型实参。这通常是为了与不使用泛型的代码进行兼容或避免繁琐的类型参数指定。

使用裸类型存在以下风险和问题:

  • 编译时类型安全性缺失:裸类型绕过了泛型的类型检查机制,编译器无法对其进行类型安全性检查。这可能导致在运行时出现类型转换错误或其他类型相关的异常。
  • 运行时类型错误:由于裸类型丢失了具体的类型信息,可能导致在运行时发生ClassCastException等类型错误。
  • 代码可读性和维护性下降:使用裸类型会降低代码的可读性和可维护性,因为泛型的意图和约束没有明确表达出来,代码的含义变得模糊。

当使用裸类型时,编译器会发出未经检查的警告。下面是一个使用裸类型的例子:

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

public class RawTypeExample {
    public static void main(String[] args) {
        List list = new ArrayList(); // 使用裸类型

        list.add("Hello");
        list.add(123);

        // 从列表中获取元素时,无法保证类型的安全性
        String str = (String) list.get(0); // 运行时可能会发生ClassCastException
        int number = (int) list.get(1); // 运行时可能会发生ClassCastException

        System.out.println(str);
        System.out.println(number);
    }
}

在上面的示例中,我们创建了一个ArrayList的裸类型对象,并向其添加了一个字符串和一个整数。然后,我们尝试从列表中获取元素并进行类型转换。由于裸类型丢失了具体的类型信息,编译器无法在编译时捕获类型错误。因此,当我们运行该代码时,可能会抛出ClassCastException。

要修复这个问题,我们应该使用泛型类型参数来明确指定列表的类型。下面是一个修复后的示例:

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

public class GenericTypeExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>(); // 使用泛型类型

        list.add("Hello");
        // list.add(123); // 编译错误,无法将整数添加到字符串列表中

        String str = list.get(0); // 不需要进行类型转换
        System.out.println(str);
    }
}

在这个修复后的示例中,我们使用了泛型类型参数<String>来明确指定列表的类型为字符串类型。这样,编译器会在编译时进行类型检查,并阻止将整数添加到字符串列表中。这提供了更好的类型安全性,并在编译时捕获潜在的类型错误。

为了避免使用裸类型,应该尽量遵循泛型的使用规范,为泛型类型参数指定具体类型实参,并尽量避免显式使用裸类型。这样可以确保代码的类型安全性,并使代码更易于理解和维护。同时,应该警惕编译器发出的未经检查的警告,并尽量修复这些警告,以提高代码质量。

List

List是Java集合框架中的一个接口,它表示一个有序的、可重复的元素集合。List接口继承自Collection接口,并在其基础上添加了一些与索引相关的操作方法。

这是List 的官方文档:列表 (Java Platform SE 8 ) (oracle.com)

 List的特点包括:

  • 有序性:List中的元素按照它们被添加的顺序进行存储,并且可以通过索引访问和操作元素。每个元素都有一个与之关联的索引,从0开始递增。
  • 可重复性:List中可以存储重复的元素,即同一个元素可以出现多次。
  • 动态大小:List的大小是可变的,可以根据需要动态地添加或删除元素。

List接口提供了许多常用的方法,使我们能够对集合中的元素进行增加、删除、修改、查找等操作。一些常用的List实现类包括:

  • ArrayList:基于数组实现的动态数组,支持快速随机访问,但插入和删除操作可能较慢。
  • LinkedList:基于链表实现的双向链表,支持快速的插入和删除操作,但随机访问较慢。
  • Vector:类似于ArrayList,但是是线程安全的,适用于多线程环境。
  • Stack:基于Vector实现的栈数据结构,支持先入后出的操作。

List接口提供了一系列的方法,如:

添加元素:add、addAll
获取元素:get、indexOf、lastIndexOf
删除元素:remove、removeAll、clear
修改元素:set
遍历元素:forEach、iterator、listIterator
判断元素是否存在:contains、isEmpty
获取列表大小:size
截取子列表:subList
其他:sort、reverse、shuffle等

List的灵活性和功能丰富性使得它成为Java中常用的集合类型之一,可以方便地操作和管理有序的元素集合。无论是需要保持元素顺序、支持重复元素,还是进行索引操作,List都是一个很好的选择。

注意:在编程中,一般会使用 List<String> ad = new ArrayList<>(); 的形式来创建 ArrayList 对象,因为这样代码的可读性更好,而且灵活性更高。这是因为,List 接口是 ArrayList 类的一个父接口,通过使用 List 类型的引用来指向 ArrayList 对象,可以使代码更具有通用性。这样写的好处是,以后如果需要更改为其他类型的 List(如 LinkedList),只需要改变声明的时候的类型,而不需要修改实例化的代码。

虽然直接使用 ArrayList<String> ad = new ArrayList<>(); 也是可以的,但是不够灵活,不利于后期代码的维护和扩展。当然,使用 ArrayList<String> ad = new ArrayList<>(); 也有好处,它能够调用的方法更多。

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

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

相关文章

LC-1335. 工作计划的最低难度(区间DP、记忆化搜索==>动态规划)

1335. 工作计划的最低难度 难度困难97 你需要制定一份 d 天的工作计划表。工作之间存在依赖&#xff0c;要想执行第 i 项工作&#xff0c;你必须完成全部 j 项工作&#xff08; 0 < j < i&#xff09;。 你每天 至少 需要完成一项任务。工作计划的总难度是这 d 天每一…

JavaSE进阶(一)—— 面向对象进阶(static、单例、代码块、继承)

目录 一、static静态关键字 1. static是什么&#xff0c;static修饰成员变量的用法 2. 成员方法的分类 2.1 使用场景 3. static修饰成员方法的内存原理 4. static的注意事项[拓展] 二、static应用知识&#xff1a;工具类 1. 工具类是什么 2. 工具类的好处 3. 为什么工…

域名信息收集

被动信息收集 0x01 Certificate Transparency&#xff08;证书透明&#xff09; 证书透明度(Certificate Transparency)是证书授权机构的一个项目&#xff0c;证书授权机构会将每个SSL/TLS证书发布到公共日志中。一个SSL/TLS证书通常包含域名、子域名和邮件地址。查找某个域名…

Java进阶-字符串的使用

1.API 1.1API概述 什么是API ​ API (Application Programming Interface) &#xff1a;应用程序编程接口 java中的API ​ 指的就是 JDK 中提供的各种功能的 Java类&#xff0c;这些类将底层的实现封装了起来&#xff0c;我们不需要关心这些类是如何实现的&#xff0c;只需要…

PPT技能之描边字,要大要醒目别整没用的

文字仅仅加粗&#xff0c;还是不够明显&#xff0c;不妨用上描边字。不会Photoshop&#xff0c;不会PS&#xff0c;也可以做好看的描边字。 描边字&#xff0c;是在文字的边缘加上边框&#xff0c;让文字更醒目、突出。 你的关注&#xff0c;是我最大的动力&#xff01;你的转…

【K8s】基本存储、高级存储(PV和PVC)、配置存储

文章目录 背景一、基本存储1、EmptyDir2、HostPath3、NFS 二、高级存储1、认识PV和PVC2、PV3、PVC4、生命周期 三、配置存储1、ConfigMap2、 Secret 背景 程序运行在容器中&#xff0c;而容器的生命周期可能极其短暂&#xff0c;容器销毁&#xff0c;数据丢失&#xff0c;因此…

pip install出现socket.timeout: The read operation timed out的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

MySQL 8.0不再担心被垃圾SQL搞爆内存

MySQL 8.0.28引入的新功能 MySQL 8.0.28开始&#xff0c;新增一个特性&#xff0c;支持监控统计并限制各个连接&#xff08;会话&#xff09;的内存消耗&#xff0c;避免大量用户连接因为执行垃圾SQL消耗过多内存&#xff0c;造成可能被OOM kill的风险。 首先&#xff0c;需要…

【Servlet】图解HTTP请求Tomcat服务器实现前后端交互

文章目录 前言如何构造HTTP请求&#xff1f;1、通过form表单构造HTTP请求① form发送GET请求② form发送POST请求 2、通过Ajax构造HTTP请求同步等待与异步等待的感性理解 3、使用postman构造HTTP请求4、通过 Java socket 构造 HTTP 请求 如何实现前端给后端传参1、query string…

Jetpack Compose 中的debug调试

之前在 Jetpack Compose 中的重组作用域和性能优化 一文中主要介绍了如何从代码层面进行一些优化以及提到了一些值得注意的优化事项&#xff0c;本文主要来了解一下官方提供了哪些工具层面的手段可以帮助我们进行Compose的debug性能调试。 常规debug方式 这个跟以前的方式一样…

『python爬虫』22. 初识自动化测试工具selenium(保姆级图文)

目录 1. selenium的安装配置2. 为什么使用selenium&#xff1f;它的优势和缺点是什么&#xff1f;3. selenium的基本使用4. selenium实战之csdn搜索python博文4.1 点击选择文章4.2 搜索栏输入搜索关键词4.3 实现代码 总结 欢迎关注 『python爬虫』 专栏&#xff0c;持续更新中 …

【MYSQL】索引的原理(B+树实现)和操作

目录 1.MYSQL与磁盘交互的基本单位 2.索引的原理 3.聚簇索引 4.索引操作 认识磁盘 1.MYSQL与磁盘交互的基本单位 为了提高基本的IO效率&#xff0c; MySQL进行IO的基本单位是16KB 一次使用16KB&#xff08;称为page&#xff09;为单位大于磁道的扇面&#xff08;521B&…

Golang笔记:使用ssh包作为客户端与SSH服务器交互

文章目录 目的基础说明使用演示单次通讯连续通讯&#xff08;远程终端&#xff09; 总结 目的 Golang中可以使用 golang.org/x/crypto/ssh 包作为SSH客户端或者SSH服务使用。这篇文章将简单记录下作为客户端使用的一些内容。 Package ssh implements an SSH client and server…

Java基础 开发相关的介绍和准备(开发环境搭建)

Java 概述 是 SUN(Stanford University Network&#xff0c;斯坦福大学网络公司 ) 1995 年推出的一门高级 编程语言。 是一种面向 Internet 的编程语言。Java 一开始富有吸引力是因为 Java 程序可以在 Web 浏览器中运行。这些 Java 程序被称为 Java 小程序(applet)&#xff0c…

学系统集成项目管理工程师(中项)系列22a_信息化知识(上)

1. 战略资源 1.1. 信息 1.2. 土地 1.3. 能源 1.4. 材料 2. 信息information 2.1. 客观事物状态和运动特征的一种普遍形式 2.2. 控制论 2.2.1. 维纳Norbert Wiener 2.2.2. 信息就是信息&#xff0c;既不是物质也不是能量 2.3. 哲学界 2.3.1. 信息是事物普遍联系的方式…

通过xshell连接甲骨文服务器并安装宝塔详细图文教程避免踩坑

问题&#xff1a; 一&#xff0c;甲骨文创建好了&#xff0c;并且下载了私钥&#xff0c;怎么连接&#xff1f;忘记下载了怎么办&#xff1f; 二&#xff0c;xshell怎么使用&#xff1f; 三&#xff0c;宝塔怎么安装&#xff1f; 起点&#xff1a; 最近有幸注册了一个甲骨…

SpringBoot--Lombok--Initailizr--yaml

目录 SpringBoot--Lombok Lombok 介绍 ● Lombok 作用 ● SpringBoot 和IDEA 官方支持 Lombok 常用注解 Lombok 应用实例 代码实现 在pom.xml 引入lombok 修改Furn.java 使用Lombok 注解简化代码, 解读 NoArgsConstructor AllArgsConstructor ToString Setter Ge…

多种方法解决Please specify which branch you want to merge with的错误

文章目录 1. 复现错误2. 分析错误3. 解决错误3.1 远程有分支3.2 远程无分支 4. 总结 1. 复现错误 今天发布某版本的项目&#xff0c;准备创建个v0point1分支&#xff0c;后期如果修改该版本&#xff0c;直接在该分支上修改即可。 首先&#xff0c;使用git branch v0point1命令…

软考A计划-真题-分类精讲汇总-第十三章(专业英语)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

红黑树的实现

文章目录 红黑树前言1. 红黑树的概念及性质1.1 红黑树的概念1.2 红黑树的性质 2. 红黑树的结构2.1 红黑树节点的定义2.2 红黑树的结构 3. 红黑树的操作3.1 红黑树的查找3.2 红黑树的插入处理红黑树颜色的过程(重点)情况1: 只变色情况2: 变色 单旋情况3: 变色 双旋 处理颜色的…