揭秘字符串的奥秘:探索String类的深层含义与源码解读

文章目录

    • 一、导论
      • 1.1 引言:字符串在编程中的重要性
      • 1.2 目的:深入了解String类的内部机制
    • 二、String类的设计哲学
      • 2.1 设计原则:为什么String类如此重要?
      • 2.2 字符串池的概念与作用
    • 三、String类源码解析
      • 3.1 成员变量
      • 3.2 构造函数
      • 3.3 equals(): 判断两个对象是否相等
      • 3.4 charAt(): 获取指定位置的字符
      • 3.5 length(): 获取字符串长度
      • 3.6 concat(): 字符串连接
      • 3.7 substring(): 子串提取
      • 3.8 compareTo (): 字符串长度相等的比较
      • 3.9 hashCode():重写hashCode
      • 3.10 replace ():新值替换旧值
      • 3.11 trim():去除空格
      • 3.12 startsWith():前缀+后缀
    • 四、String类的内部实现机制
      • 4.1 字符串的存储方式:常量池、堆、栈
      • 4.2 字符串不可变性的实现细节
    • 五、性能优化与字符串操作技巧
      • 5.1 使用StringBuilder和StringBuffer提高字符串拼接效率
      • 5.2 字符串比较的最佳实践
    • 六、案例分析与实例演示
      • 6.1 实际代码示例:如何更好地使用String类
      • 6.2 常见陷阱与解决方案

一、导论

1.1 引言:字符串在编程中的重要性

字符串在编程中非常重要,因为它们是处理文本数据的基本单位。在几乎所有编程语言中,都有专门的字符串类型和相关的操作方法,这些方法使得处理文本变得更加方便和灵活。

字符串在编程中的重要性

  1. 文本处理: 字符串用于存储和处理文本数据。无论是读取文件、用户输入还是与外部系统通信,都需要使用字符串。
  2. 数据表示: 许多数据格式,如JSON、XML和HTML,都使用字符串来表示结构化的数据。在这些情况下,字符串是将数据进行序列化和反序列化的基础。
  3. 用户界面: 用户界面中的文本标签、按钮标签等通常都是字符串。程序需要能够操作和显示这些字符串以与用户进行交互。
  4. 搜索和匹配: 字符串操作是执行搜索、替换和匹配操作的基础。正则表达式是一种强大的工具,用于在字符串中进行复杂的模式匹配。
  5. 密码学和安全性: 字符串在密码学中的使用非常广泛。加密和哈希算法通常对字符串进行操作,以确保数据的安全性。
  6. 网络通信: 在网络通信中,数据通常以字符串的形式传输。这包括HTTP请求和响应、数据库查询和响应等。
  7. 程序逻辑: 在编程中,字符串也常常用于表示程序中的命令、条件和逻辑结构。例如,条件语句中的比较操作就涉及到字符串的比较。

总体而言,字符串在编程中是一个不可或缺的组成部分,广泛用于处理和表示各种类型的文本数据。

1.2 目的:深入了解String类的内部机制

在Java中,String类是不可变的,这意味着一旦字符串对象被创建,它的内容就不能被修改。

String类内部机制的重要信息:

  1. 不可变性(Immutability): String类的不可变性是通过将字符数组(char数组)声明为final并使用private final char value[]来实现的。这意味着一旦字符串被创建,它的内容不能被更改。
  2. 字符串池(String Pool): Java中的字符串池是一种特殊的存储区域,用于存储字符串常量。当你创建一个字符串时,JVM首先检查字符串池是否已经存在相同内容的字符串,如果存在则返回池中的引用,否则创建一个新的字符串对象并放入池中。
  3. 常量池(Constant Pool): 字符串池实际上是常量池的一部分,其中存储了类、方法和接口中的常量数据。字符串常量池属于这个常量池。
  4. StringBuilder和StringBuffer: 在Java中,如果需要对字符串进行频繁的修改,建议使用StringBuilder(非线程安全)或StringBuffer(线程安全)而不是String。这是因为StringBuilderStringBuffer类提供了可变的字符串,避免了每次修改都创建新的字符串对象的开销。
  5. 字符串连接: 字符串连接使用+运算符时,实际上是创建了一个新的字符串对象。对于频繁的字符串连接操作,最好使用StringBuilderStringBuffer以提高性能。
  6. 字符串比较: 使用equals()方法来比较字符串的内容,而不是使用==运算符。equals()方法比较字符串的实际内容,而==运算符比较的是对象引用。
  7. 字符串不可变性的好处: 不可变字符串有助于线程安全,可以安全地在多个线程中共享,而无需担心数据被修改。此外,不可变性还有助于缓存字符串,提高性能。

总的来说,了解String类的内部机制有助于更有效地使用字符串,理解字符串的创建、比较和连接等操作的性能影响。

二、String类的设计哲学

2.1 设计原则:为什么String类如此重要?

String类之所以如此重要,主要是因为字符串在计算机编程中是一种非常常用的数据类型,而Java的String类提供了丰富的方法和功能,使得字符串的处理变得更加方便和灵活。

String类的重要特点和用途:

  1. 不可变性(Immutable): String类的实例是不可变的,一旦创建了字符串对象,就不能再修改它的值。这使得字符串在多线程环境下更安全,也更容易进行优化。

  2. 字符串连接和拼接: String类提供了丰富的方法来进行字符串的连接和拼接,例如使用+运算符或者concat()方法。这使得构建复杂的字符串变得简单,而且性能较好。

    String firstName = "John";
    String lastName = "Doe";
    String fullName = firstName + " " + lastName;
    
  3. 字符串比较: String类提供了用于比较字符串的方法,如equals()compareTo()。这些方法使得比较字符串内容变得方便,可以轻松地判断两个字符串是否相等。

    String str1 = "hello";
    String str2 = "world";
    if (str1.equals(str2)) {
        // 字符串内容相等
    }
    
  4. 字符串操作: String类包含许多有用的方法,如length()charAt()substring()等,可以对字符串进行各种操作,例如获取字符串长度、访问特定位置的字符、提取子串等。

    String text = "Hello, World!";
    int length = text.length(); // 获取字符串长度
    char firstChar = text.charAt(0); // 获取第一个字符
    String subString = text.substring(0, 5); // 提取子串
    
  5. 正则表达式: String类提供了支持正则表达式的方法,可以用于字符串的模式匹配和替换操作。

    String text = "The quick brown fox jumps over the lazy dog";
    String replacedText = text.replaceAll("fox", "cat");
    
  6. 国际化(Internationalization): String类提供了支持国际化的方法,可以处理不同语言和字符集的字符串。

String类的重要性在于它为字符串的处理提供了丰富的工具和方法,使得在Java中进行字符串操作变得更加方便、高效和安全。

2.2 字符串池的概念与作用

当谈到Java中的字符串池时,我们通常指的是字符串常量池,它是Java中用于存储字符串常量的一个特殊区域。

  1. 概念
    • 字符串池是一个位于堆区的特殊存储区域,用于存储字符串常量。
    • 字符串池是Java运行时数据区的一部分,它有助于提高字符串的重用性和节省内存。
  2. 作用
    • 字符串重用:字符串池确保相同内容的字符串在内存中只有一份。当你创建一个字符串常量时,Java首先检查字符串池中是否已经存在相同内容的字符串,如果存在,则返回池中的引用,而不是创建一个新的对象。
    • 节省内存:通过重用相同的字符串,避免了在内存中创建多个相同内容的字符串对象,从而节省了内存空间。
    • 提高性能:由于字符串常量池减少了相同字符串的创建和销毁,因此可以提高程序的性能。

下面是一个简单的例子,说明字符串池的工作方式:

String s1 = "Hello";  // 创建字符串常量 "Hello",存储在字符串池中
String s2 = "Hello";  // 直接引用字符串池中的 "Hello",不会创建新的对象

System.out.println(s1 == s2);  // 输出 true,因为它们引用的是相同的字符串对象

**解释:**由于字符串"Hello"在字符串池中已经存在,因此s2直接引用了已有的对象,而不是创建新的对象。这种字符串池的机制有助于提高内存利用率和程序性能。

三、String类源码解析

3.1 成员变量

在这里插入图片描述

3.2 构造函数

// 默认构造函数
public String() {
    // 通过空字符串的值("")来初始化新创建的字符串对象的值
    this.value = "".value;
}

// 带有 String 类型参数的构造函数
public String(String original) {
    // 将新创建的字符串对象的值设置为原始字符串对象的值
    // value 和 hash 是 String 对象的内部属性
    this.value = original.value; // 通过访问原始字符串对象的 value 属性来获取其值
    this.hash = original.hash; // 获取原始字符串对象的哈希码(hash code)
}

// 带有 char 数组参数的构造函数,使用 java.utils 包中的 Arrays 类进行复制
public String(char value[]) {
    // 使用 Arrays 类的 copyOf 方法复制传入的 char 数组
    // 将复制后的数组作为新字符串对象的值
    this.value = Arrays.copyOf(value, value.length);
}

// 用于根据给定的字符数组、偏移量和长度创建一个新的字符串对象
public String(char value[], int offset, int count) {
    // 检查偏移量是否小于零
    if (offset < 0) {
        // 表示字符串索引越界
       throw new StringIndexOutOfBoundsException(offset);
    }
    // 检查长度是否小于等于零
    if (count <= 0) {
        if (count < 0) {
            // 表示字符串索引越界
           throw new StringIndexOutOfBoundsException(count);
        }
        // 如果长度为零,并且偏移量在字符数组的范围内,则将新字符串的值设置为空字符串,然后返回
        // 为了处理特殊情况,以防止数组越界
        if (offset <= value.length) {
           this.value = "".value;
           return;
        }
    }
    // 检查偏移量和长度的组合是否超出了字符数组的范围
    // Note: offset or count might be near -1>>>1.
    if (offset > value.length - count) {
        // 字符串索引越界
       throw new StringIndexOutOfBoundsException(offset + count);
    }
    // 如果通过了所有检查,使用Arrays.copyOfRange方法从输入字符数组中复制指定偏移量和长度的部分,然后将这个部分作为新字符串的值。
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}

// 接受一个字节数组 bytes,一个偏移量 offset,一个长度 length,以及一个字符集名称 charsetName
// 目的是将字节数组以指定的字符集解码成字符串
public String(byte bytes[], int offset, int length, String charsetName)
       throws UnsupportedEncodingException {
    // 参数表示要使用的字符集的名称,如果为 null,则抛出 NullPointerException 异常
   if (charsetName == null)
       throw new NullPointerException("charsetName");
    // 检查偏移量和长度是否在字节数组的有效范围内
   checkBounds(bytes, offset, length);
    // 用于实际的解码过程,将字节数组转换为字符串,并将结果存储在 this.value 字段中
   this.value = StringCoding.decode(charsetName, bytes, offset, length);
}

// 使用字节数组的全部内容,并将偏移量设置为0,长度设置为字节数组的长度。通过调用上一个构造方法来完成实际的字符串解码
public String(byte bytes[], String charsetName)
      throws UnsupportedEncodingException {
   this(bytes, 0, bytes.length, charsetName);
}

// 接受一个 StringBuffer 对象 buffer,并将其内容复制到新创建的 String 对象中
public String(StringBuffer buffer) {
    // 通过对 buffer 对象进行同步,确保在复制过程中没有其他线程对其进行修改
    synchronized(buffer) {
        // 使用 Arrays.copyOf 方法来复制字符数组,然后将结果存储在 this.value 字段中
        this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
    }
}

3.3 equals(): 判断两个对象是否相等

在这里插入图片描述

3.4 charAt(): 获取指定位置的字符

在这里插入图片描述

3.5 length(): 获取字符串长度

在这里插入图片描述

3.6 concat(): 字符串连接

在这里插入图片描述

3.7 substring(): 子串提取

在这里插入图片描述

3.8 compareTo (): 字符串长度相等的比较

在这里插入图片描述

3.9 hashCode():重写hashCode

在这里插入图片描述

3.10 replace ():新值替换旧值

在这里插入图片描述

3.11 trim():去除空格

在这里插入图片描述

3.12 startsWith():前缀+后缀

在这里插入图片描述

四、String类的内部实现机制

4.1 字符串的存储方式:常量池、堆、栈

在Java中,字符串可以存储在常量池(String Pool)、堆内存(Heap)和栈内存(Stack)中,具体取决于字符串的创建方式和使用情况。

  1. 常量池(String Pool):
    • 字符串池是常量池的一部分,用于存储字符串常量。
    • 当你使用字符串字面量创建一个字符串时,例如String str = "Hello";,字符串常量"Hello"会存储在常量池中。
    • 如果已经存在相同内容的字符串常量,那么新的字符串引用会指向已存在的字符串常量,而不会创建新的对象。
  2. 堆内存(Heap):
    • 当使用new关键字创建字符串对象时,例如String str = new String("Hello");,字符串对象会存储在堆内存中。
    • 不管字符串内容是否相同,每次使用new都会在堆内存中创建一个新的字符串对象,即使内容相同也会占用不同的内存空间。
  3. 栈内存(Stack):
    • 字符串引用变量(例如String str = ...;)本身存储在栈内存中,而不是字符串内容。
    • 如果一个方法内部创建了一个字符串对象,该引用变量也会存储在栈内存中。

下面是一个简单的示例,说明了字符串在常量池和堆中的存储方式:

String str1 = "Hello"; // 存储在常量池
String str2 = "Hello"; // 直接引用常量池中的"Hello"

String str3 = new String("Hello"); // 存储在堆内存
String str4 = new String("Hello"); // 存储在堆内存,不同于str3

System.out.println(str1 == str2); // true,因为引用的是同一个常量池中的对象
System.out.println(str3 == str4); // false,因为使用了new关键字,创建了两个不同的对象

请注意,对于字符串的比较,应该使用equals()方法而不是==运算符,因为==比较的是引用是否相同,而equals()比较的是字符串的内容是否相同。

4.2 字符串不可变性的实现细节

在Java中,字符串的不可变性是通过以下方式实现的:

  1. final修饰符: Java中的String类被声明为final,这意味着它不能被继承。因此,无法创建String类的子类来修改其行为。
  2. 字符数组: 字符串在Java内部是通过字符数组(char array)实现的。这个字符数组被声明为final,并且它的引用是私有的,因此外部无法直接访问。
  3. 不可变性方法: String类中的大多数方法都被设计为不会修改字符串本身,而是返回一个新的字符串。例如,concatsubstringreplace等方法都是返回新的字符串对象而不是修改原始字符串。
  4. StringBuilder和StringBuffer的区别: 如果需要对字符串进行频繁的修改,可以使用StringBuilder或者在多线程环境下使用StringBuffer。这两者与String不同,它们是可变的。StringBuilderStringBuffer允许修改其内部的字符序列,因此它们的性能可能更好。

虽然字符串是不可变的,但Java中的字符串池(String Pool)提供了一种机制,可以在一定程度上重用字符串对象,以提高性能和节省内存。字符串池可以通过String.intern()方法来使用。这个方法会在字符串池中查找相等的字符串,如果找到则返回池中的实例,否则将字符串添加到池中并返回。这种机制有助于减少内存占用,因为相同的字符串在池中只存在一份。

总的来说,Java中字符串的不可变性是通过final关键字、私有字符数组和返回新字符串的方法等多个机制来实现的。

五、性能优化与字符串操作技巧

5.1 使用StringBuilder和StringBuffer提高字符串拼接效率

在Java中,StringBuilderStringBuffer都是用于处理字符串拼接的类,它们的设计目的是为了提高字符串操作的效率,特别是在涉及大量字符串拼接的情况下。

主要区别在于它们的线程安全性:

  1. StringBuilder: 是非线程安全的,适用于单线程环境下的字符串拼接。由于不需要考虑线程同步的开销,通常比StringBuffer性能稍好。

    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("Hello");
    stringBuilder.append(" ");
    stringBuilder.append("World");
    String result = stringBuilder.toString();
    
  2. StringBuffer: 是线程安全的,适用于多线程环境下的字符串拼接。它使用了同步方法,因此在多线程情况下可以确保操作的原子性,但这也导致了一些性能开销。

    StringBuffer stringBuffer = new StringBuffer();
    stringBuffer.append("Hello");
    stringBuffer.append(" ");
    stringBuffer.append("World");
    String result = stringBuffer.toString();
    
    

在实际使用中,如果你的应用是单线程的,建议使用StringBuilder,因为它相对更轻量。如果涉及到多线程操作,并且需要保证线程安全性,可以选择使用StringBuffer。总的来说,在大多数情况下,StringBuilder更常见,因为很多场景下不需要关心线程安全性。

5.2 字符串比较的最佳实践

在Java中进行字符串比较时,有几种不同的方法,而选择哪种方法通常取决于你的具体需求。

下面是一些在Java中进行字符串比较的最佳实践

  1. 使用equals方法:

    String str1 = "Hello";
    String str2 = "World";
    
    if (str1.equals(str2)) {
        // 字符串相等
    }
    
    

    这是最基本的字符串比较方法。使用equals方法比较字符串的内容是否相同。

  2. 忽略大小写比较:

    String str1 = "Hello";
    String str2 = "hello";
    
    if (str1.equalsIgnoreCase(str2)) {
        // 忽略大小写,字符串相等
    }
    
    

    使用equalsIgnoreCase方法来执行大小写不敏感的比较。

  3. 使用compareTo方法:

    String str1 = "Hello";
    String str2 = "World";
    
    int result = str1.compareTo(str2);
    
    if (result == 0) {
        // 字符串相等
    } else if (result < 0) {
        // str1 小于 str2
    } else {
        // str1 大于 str2
    }
    
    

    compareTo方法返回一个整数,表示两个字符串的大小关系。

  4. 使用Objects.equals方法(防止空指针异常):

    String str1 = "Hello";
    String str2 = "World";
    
    if (Objects.equals(str1, str2)) {
        // 字符串相等,包括处理空指针异常
    }
    
    

    Objects.equals方法可以防止在比较时出现空指针异常。

  5. 使用StringUtils.equals方法(Apache Commons Lang库):

    import org.apache.commons.lang3.StringUtils;
    
    String str1 = "Hello";
    String str2 = "World";
    
    if (StringUtils.equals(str1, str2)) {
        // 字符串相等,包括处理空指针异常
    }
    
    

    如果你使用Apache Commons Lang库,可以使用其中的StringUtils.equals方法来进行字符串比较,它也能处理空指针异常。

六、案例分析与实例演示

6.1 实际代码示例:如何更好地使用String类

在Java中,String类是一个常用的类,用于表示字符串并提供了许多方法来处理字符串。

以下是一些使用String类的实际代码示例,展示了如何更好地利用该类的一些常见方法:

  1. 字符串的基本操作:
public class StringExample {
    public static void main(String[] args) {
        // 创建字符串
        String str1 = "Hello";
        String str2 = "World";

        // 字符串连接
        String result = str1 + ", " + str2;
        System.out.println(result);

        // 获取字符串长度
        int length = result.length();
        System.out.println("Length: " + length);

        // 字符串比较
        boolean isEqual = str1.equals(str2);
        System.out.println("Are strings equal? " + isEqual);

        // 忽略大小写比较
        boolean isEqualIgnoreCase = str1.equalsIgnoreCase("hello");
        System.out.println("Are strings equal (ignore case)? " + isEqualIgnoreCase);

        // 提取子字符串
        String substring = result.substring(0, 5);
        System.out.println("Substring: " + substring);

        // 查找字符或子字符串的位置
        int index = result.indexOf("World");
        System.out.println("Index of 'World': " + index);
    }
}

  1. 使用StringBuilder进行字符串拼接:
public class StringBuilderExample {
    public static void main(String[] args) {
        // 使用StringBuilder进行字符串拼接
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("Hello");
        stringBuilder.append(", ");
        stringBuilder.append("World");

        // 转换为String
        String result = stringBuilder.toString();
        System.out.println(result);
    }
}

  1. 字符串的拆分与连接:
public class SplitJoinExample {
    public static void main(String[] args) {
        // 字符串拆分
        String names = "John,Jane,Jim";
        String[] nameArray = names.split(",");
        for (String name : nameArray) {
            System.out.println("Name: " + name);
        }

        // 字符串连接
        String joinedNames = String.join("-", nameArray);
        System.out.println("Joined Names: " + joinedNames);
    }
}

6.2 常见陷阱与解决方案

在Java中,String类是一个常用的类,但在使用过程中可能会遇到一些陷阱。以下是一些常见的String类使用陷阱及其解决方案:

  1. 字符串拼接的陷阱

    • 陷阱:使用+运算符进行字符串拼接时,每次拼接都会创建一个新的String对象,效率较低。
    • 解决方案:使用StringBuilder类进行字符串拼接,它是可变的,可以减少对象的创建。
    StringBuilder sb = new StringBuilder();
    sb.append("Hello");
    sb.append(" ");
    sb.append("World");
    String result = sb.toString();
    
    
  2. 字符串比较的陷阱

    • 陷阱:使用==比较字符串内容,这比较的是对象的引用而不是内容。
    • 解决方案:使用equals()方法进行字符串内容的比较。
    String str1 = "Hello";
    String str2 = new String("Hello");
    if (str1.equals(str2)) {
        // 内容相等
    }
    
    
  3. 不可变性的陷阱

    • 陷阱:String对象是不可变的,每次对字符串进行修改都会创建新的对象,可能导致性能问题。
    • 解决方案:如果需要频繁修改字符串,可以使用StringBuilderStringBuffer,它们是可变的。
    StringBuilder sb = new StringBuilder("Hello");
    sb.append(" World");
    String result = sb.toString();
    
    
  4. 空字符串处理的陷阱

    • 陷阱:未对空字符串进行判空处理可能导致空指针异常。
    • 解决方案:始终在使用字符串之前检查是否为null或空字符串。
    String str = ...; // 从其他地方获取的字符串
    if (str != null && !str.isEmpty()) {
        // 执行操作
    }
    
    
  5. 字符串常量池的陷阱

    • 陷阱:使用new String()方式创建字符串对象时,不会在常量池中进行缓存,可能导致不必要的内存消耗。
    • 解决方案:直接使用字符串字面量,或者使用intern()方法将字符串对象放入常量池。
    String str1 = "Hello"; // 位于常量池
    String str2 = new String("Hello").intern(); // 放入常量池
    
    

这些是一些常见的String类使用陷阱及其解决方案。在开发中,始终注意字符串的不可变性和性能问题,选择适当的方式来处理字符串操作。

盈若安好,便是晴天

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

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

相关文章

【小聆送书第二期】人工智能时代之AIGC重塑教育

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;正文&#x1f4dd;活动参与规则 参与活动方式文末详见。 &#x1f4cb;正文 AI正迅猛地…

ubuntu 20.04 server 安装 zabbix

ubuntu 20.04 server 安装 zabbix 参考文档 zabbix没用过&#xff0c;用过prometheus&#xff0c; 因为现在很多应用都支持直接接入prometheus监控&#xff0c; 而且大部分语言都都有sdk支持&#xff0c; 可以直接接入自己的业务数据监控。 https://www.zabbix.com/cn/downlo…

激光打标机在智能手表上的应用:科技与时尚的完美结合

随着科技的飞速发展&#xff0c;智能手表已经成为我们日常生活中不可或缺的智能设备。而在智能手表制造中&#xff0c;激光打标机扮演着至关重要的角色。本文将详细介绍激光打标机在智能手表制造中的应用&#xff0c;以及其带来的优势和影响。 ​ 一、激光打标机在智能手表制…

MySql-substring函数和substring_index函数的使用及练习

目录 13.2.1 substring函数 1. 概述 2. 使用格式 3. 参数列表 4. 实例练习 13.2.2 substring_index函数 1. 概述 2. 格式 3. 参数说明 4. 返回值 5. 实例练习1 6. 实例练习2 13.3 牛客练习题 13.2.1 substring函数 1. 概述 substring函数是文本处理函数&#xf…

C语言 占位符 + 转义字符 + ASCLL 表 + 缓冲区

整型 占位符 取值范围 浮点型 占位符 转义字符 注意&#xff1a;绿色字体标注的为不可打印字符。 printf 常用占位符&#xff1a; printf 附加格式 ASCII 表 标准ASCII码的范围是0&#xff5e;127&#xff0c;只需7位二进制数即可表示。 缓冲区 缓冲区分类&#xff1a; sizeof(…

【数据结构】——排序篇(中)

前面我们已经了解了几大排序了&#xff0c;那么我们今天就来再了解一下剩下的快速排序法&#xff0c;这是一种非常经典的方法&#xff0c;时间复杂度是N*logN。 快速排序法&#xff1a; 基本思想为&#xff1a;任取待排序元素序列中的某元素作为基准值&#xff0c;按照该排序码…

自动驾驶学习笔记(十六)——目标跟踪

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo 社区开发者圆桌会》免费报名—>传送门 文章目录 前言 匹配关联 轨迹记录 状态预测 总结 前…

C++使用策略模式,减少使用switch...case...

目录 原理函数类模板函数使用switch...case...不使用switch...case... 知识点decltypestd::remove_reference 原理 函数 #include <iostream> #include <functional> #include <map>void fun1(int a, int b) {std::cout << "fun1 : a "<…

uniApp项目的创建,运行到小程序

一、项目创建 1. 打开 HBuilder X 2. 右击侧边栏点击新建&#xff0c;选择项目 3. 填写项目名&#xff0c;点击创建即可 注&#xff1a;uniapp中如果使用生命周期钩子函数&#xff0c;建议使用哪种 ?(建议使用Vue的) 二、运行 1. 运行前先登录 2. 登录后点击 manifest.js…

Linux和Windows环境下如何使用gitee?

1. Linux 1.1 创建远程仓库 1.2 安装git sudo yum install -y git 1.3 克隆远程仓库到本地 git clone 地址 1.4 将文件添加到git的暂存区&#xff08;git三板斧之add&#xff09; git add 文件名 # 将指定文件添加到git的暂存区 git add . # 添加新文件和修改过的…

golang开发之个微机器人的二次开发

简要描述&#xff1a; 下载消息中的文件 请求URL&#xff1a; http://域名地址/getMsgFile 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型…

测试用文章2

clion编辑器安装注意事项 clion是个非常优秀的cIDE&#xff0c;能大幅度提高我们写c的效率&#xff0c;最重要的是开箱即用。不过有些设置和注意事项&#xff0c;能让我们更好地使用clion 安装ideavim插件 vim插件&#xff0c;可以设置快捷键开启和关闭&#xff0c;推荐altf&am…

Windows下nginx的启动,重启,关闭等功能bat脚本

echo off rem 提供Windows下nginx的启动&#xff0c;重启&#xff0c;关闭功能echo begincls ::ngxin 所在的盘符 set NGINX_PATHG:::nginx 所在目录 set NGINX_DIRG:\projects\nginx-1.24.0\ color 0a TITLE Nginx 管理程序增强版CLSecho. echo. ** Nginx 管理程序 *** echo.…

文心ERNIE Bot SDK+LangChain:基于文档、网页的个性化问答系统

现在各行各业纷纷选择接入大模型&#xff0c;其中最火且可行性最高的形式无异于智能文档问答助手&#xff0c;而LangChain是其中主流技术实现工具&#xff0c;能够轻松让大语言模型与外部数据相结合&#xff0c;从而构建智能问答系统。ERNIE Bot SDK已接入文心大模型4.0能力&am…

平衡二叉树

AVL简称平衡二叉树&#xff0c;缩写为BBST&#xff0c;由苏联数学家 Adelse-Velskil 和 Landis 在 1962 年提出。 二叉树是动态查找的典范&#xff0c;但在极限情况下&#xff0c;二叉树的查找效果等同于链表&#xff0c;而平衡二叉树可以完美的达到 log ⁡ 2 n \log_2 n log2…

JVM 内存分析工具 Memory Analyzer Tool(MAT)的深度讲解

目录 一. 前言 二. MAT 使用场景及主要解决问题 三. MAT 基础概念 3.1. Heap Dump 3.2. Shallow Heap 3.3. Retained Set 3.4. Retained Heap 3.5. Dominator Tree 3.6. OQL 3.7. references 四. MAT 功能概述 4.1. 内存分布 4.2. 对象间依赖 4.3. 对象状态 4.4…

docker容器配置MySQL与远程连接设置(纯步骤)

以下为ubuntu20.04环境&#xff0c;默认已安装docker&#xff0c;没安装的网上随便找个教程就好了 拉去mysql镜像 docker pull mysql这样是默认拉取最新的版本latest 这样是指定版本拉取 docker pull mysql:5.7查看已安装的mysql镜像 docker images通过镜像生成容器 docke…

Git的安装以及SSH配置

前言 近期工作需要&#xff0c;所以版本管理工具要用到Git&#xff0c;某些操作需要ssh进行操作&#xff0c;在某次操作中遇到&#xff1a;git bash报错&#xff1a;Permission denied, please try again。经排查是ssh没有配置我的key&#xff0c;所以就借着这篇文章整理了一下…

典型的ETL使用场景

典型的ETL使用场景 ETL( Extract&#xff0c;Transform&#xff0c;Load)是一种用于数据集成和数据转换的常用技术。它主要用于从多个数据源中提取数据&#xff0c;对数据进行清洗、转换和整合&#xff0c;最后加载到目标系统中。ETL 的使用场景非常广泛&#xff0c;下面将介绍…

Windows系统Java开发环境安装

总结一下Java软件开发工程师常见的环境的安装&#xff0c;仅限Windows环境。 以下下载链接均来自官网&#xff0c;网络条件自己克服。 目录 1. JDKJDK Oracle 官网下载地址配置系统环境变量 2. Mavenapache maven 官网地址本地仓库和中央仓库配置配置系统环境变量 3. GitGit 官…