Java-String

10 篇文章 0 订阅
9 篇文章 0 订阅

1 String 概述

1.1 基本介绍

  • 一个字符串是由多个字符组成的一串数据(字符序列,字符数组)

  • String类代表字符串,Java 程序中的所有字符串字面值(如 “abc” ,“你好”,“の”)都作为此类的实例实现

  • 在java.lang包下,是java核心类,最常用类,但是不属于基本数据类型,引用类型

  • String类提供了字符串表示、比较、查找、截取、大小写转换等各种针对字符串的操作

1.2 构造方法

  • 空字符串""
  • byte[] -----> String
  • char[] -----> String
  //空字符串 ""  
  public String()  

  //利用字节数组,创建字节数组所表示的字符串
  // 1. 字符 -> 数值形式  'a' -> 97
  // 2. 所以可以用多个字节值,表示多个字符——>即字符序列 public
  String(byte[] bytes)

  //利用字节数数组的一部分,创建字符序列, 从byte数组的offset开始的length个字节值
  public String(byte[] bytes,int offset,int length)

  //利用一个字符数组创建字符数组,代表的字符序列
  public String(char[] value)

  // 创建value字符数组中,从第offset位置开始的count个字符,所代表的字符串对象
  public String(char[] value,int offset,int count)
    
  //知道即可
  public String(String original)  

实例:

public class Demo1 {
    public static void main(String[] args) {
        // //空字符串 ""
        // public String()
        String s1 = new String();
        System.out.println("s1 = " + s1);

        // //利用字节数组,创建字节数组所表示的字符串
        // // 1. 字符 -> 数值形式  'a' -> 97
        // // 2. 所以可以用多个字节值,表示多个字符——>即字符序列 public
        // String(byte[] bytes)
        byte[] bytes = new byte[]{97, 98, 99, 100};
        String s2 = new String(bytes);
        System.out.println("s2 = " + s2);

        // //利用字节数数组的一部分,创建字符序列, 从byte数组的offset开始的length个字节值
        //  public String(byte[] bytes,int offset,int length)
        String s3 = new String(bytes, 1, 2);
        System.out.println("s3 = " + s3);

        // //利用一个字符数组创建字符数组,代表的字符序列
        // public String(char[] value)
        char[] chars = {'J', 'a', 'v', 'a'};
        String s4 = new String(chars);
        System.out.println("s4 = " + s4);
        // // 创建value字符数组中,从第offset位置开始的count个字符,所代表的字符串对象
        // public String(char[] value,int offset,int count)
        char[] value = {'a','b','c','H', 'e', 'l', 'l', 'o'};
        String s5 = new String(value, 3, 5);
        System.out.println("s5 = " + s5);
        // //知道即可
        // public String(String original)
        String s6 = new String("hello");
        System.out.println("s6 = " + s6);
    }
}

2 String特点(重点)

2.1 String对象不可变

对象一旦被创建后,对象所有的状态及属性在其生命周期内不会发生任何变化。

1.请键盘录入一个任意字符串s,并用一个temp字符串引用也指向它
这个时候修改temp字符串的内容,请问s字符串的内容会随之改变吗?

/*
* 对象一旦被创建后,对象所有的状态及属性在其生命周期内不会发生任何变化。

1.请键盘录入一个任意字符串s,并用一个temp字符串引用也指向它
这个时候修改temp字符串的内容,请问s字符串的内容会随之改变吗?
不会
*/
public class Demo {
    public static void main(String[] args) {
        //创建Scanner对象
        Scanner scanner = new Scanner(System.in);
        //nexiLine接收数据
        String  s = scanner.nextLine();
        // 使用temp引用指向
        String temp = s;
        //修改temp
        temp = "aaa";
        //打印temp和string
        System.out.println("temp = " + temp);
        System.out.println("s = " + s);
    }
}

原因与本质

  • String是一个final类,不能被继承, 代表不可变的字符序列
  • 字符串是常量,用双引号引起来,他们的值在创建之后不可更改
  • String对象的内容是存储在字符数组value[ ]中的
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

2.2 字符串常量池

字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串使用的非常多

JVM为了提高性能和减少内存的开销,在实例化字符串对象的时候进行了一些优化:使用字符串常量池。

首先要明确,Java的双引号引起来的字面值常量字符串,它们都是对象。这些对象比较特殊,程序在编译时期就能确定它们的值

每当创建字符串常量对象时,JVM会首先检查字符串常量池,如果该字符串对象引用已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串对象引用不存在于常量池中,就会实例化该字符串并且将其引用放到常量池中。

// 当常量池中已有字符串对象的引用时,不会在堆上再创建, 而使用同一引用
String s1 = "abc";
String s2 = "abc";

在这里插入图片描述

2.2.1 String两种实例化方式

两种方式

  • 直接赋值String s = "abc"
  • 构造方法构造方法 String s = new String("abc")

第一种 先直接赋值 再构造

String s = "abc";
String s1 = new String("abc")

image-20221013145230940第二种 先构造 再直接赋值

String s1 = new String("abc")
String s = "abc";

image-20230407081513361总结:

  • 先String s = new String(“abc”), 再String s1 = “abc”. new String 的时候会创建2个对象, 直接赋值的时候, 直接用的是常量池的引用, 不再创建新的字符串对象了
  • String s1 = “abc”, 再String s = new String(“abc”), 直接赋值的方式会创建一个对象, new String的时候会创建1个对象

2.2.2 字符串常见问题与练习

2.2.2.1 字符串比较
/*
* 字符串比较
* */
public class Demo4 {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("hello");
        System.out.println(s1 == s2);//false
        System.out.println(s1.equals(s2));//true

        String s3 = new String("hello");//创建新对象
        String s4 = "hello";//不i会创建新对象,使用s1在字符串常量池的引用
        System.out.println(s3 == s4);//false
        System.out.println(s3.equals(s4));//true

        String s5 = "hello";
        String s6 = "hello";
        System.out.println(s5 == s6);//true
        System.out.println(s5.equals(s6));//true
    }
}

==与equals方法有什么区别?

  • == ,对于基本数据类型而言,比较的是内容,对于引用数据类型而言,比较的是引用变量,即所指向的地址
  • equals方法是Object的方法,默认是比较2个对象的地址,若要比较内容,应当重写父类方法
    String中重写的equals方法image-20221013151301923
2.2.2.2 字符串拼接
/*字符串拼接*/
public class Demo5 {
    public static void main(String[] args) {
        String s1 = "Hello";
        String s2 = "Hello";
        String s3 = "Hel" + "lo";
        String s4 = "Hel" + new String("lo");
        String s5 = new String("Hello");
        String s7 = "H";
        String s8 = "ello";
        String s9 = s7 + s8;

        System.out.println(s1 == s2);// true
        System.out.println(s1 == s3);// true
        System.out.println(s1 == s4);// false
        System.out.println(s1 == s9);// false
        System.out.println(s4 == s5);// false
    }
}

image-20221013152427336进行字符串拼接的时候有2种情况

  • 当参与字符串拼接对的2个字符串,只要有1个引用变量的形式出现时,则会在堆上创建新的字符串对象.
    • 原因是因为参与了运算,无法在编译期确定其值,就不能在编译时期加入常量池
  • 只有参与字符串拼接的2个字符串都是字面值常量的时候
    • 如果常量池中已有该字符串对象的引用,则返回常量池中的引用
    • 如果常量池中没有,则在堆上创建,并把引用放入常量池

3 String API

3.1 判断功能

用来比较字符串的内容,注意区分大小写
boolean equals(Object obj)
    
忽略字符串大小写比较字符串内容,常见用于比较网址URL
boolean equalsIgnoreCase(String str)
    
判断当前字符串对象是否包含,目标字符串的字符序列 
boolean contains(String str)
    
判断当前字符串对象,是否已目标字符串的字符序列开头
boolean startsWith(String str)
    
判断当前字符串,是否以目标字符串对象的字符序列结尾,常用于确定文件后缀名格式
boolean endsWith(String str)
    
判断一个字符串,是不是空字符串 
boolean isEmpty()
/**
 * @package: _01code._01string._03api
 * @description:
 * @author: Yunyang
 * @date: 2023/10/30  11:26
 * @version:1.0
 **/
public class Demo {
    public static void main(String[] args) {
        // 用来比较字符串的内容,注意区分大小写
        // boolean equals(Object obj)
        String s1 = "hello";
        String s2 = new String("hello");
        System.out.println(s1.equals(s2));  //true


        // 忽略字符串大小写比较字符串内容,常见用于比较网址URL
        // boolean equalsIgnoreCase(String str)
        String s3 = "HELLO";
        System.out.println(s1.equals(s3));  //false
        System.out.println(s1.equalsIgnoreCase(s3));    //true


        // 判断当前字符串对象是否包含,目标字符串的字符序列
        // boolean contains(String str)
        String str = "abcdef";
        System.out.println("str.contains(\"def\") = " + str.contains("def"));   //true


        // 判断当前字符串对象,是否已目标字符串的字符序列开头
        // boolean startsWith(String str)
        System.out.println("str.startsWith(\"ab\") = " + str.startsWith("ab")); //true


        // 判断当前字符串,是否以目标字符串对象的字符序列结尾,常用于确定文件后缀名格式
        // boolean endsWith(String str)
        System.out.println("str.endsWith(\"ef\") = " + str.endsWith("ef")); //ture
        System.out.println("str.endsWith(\".exe\") = " + str.endsWith(".exe")); //false


        // 判断一个字符串,是不是空字符串
        // boolean isEmpty()
        System.out.println("str.isEmpty() = " + str.isEmpty()); //false
        System.out.println("\"\".isEmpty() = " + "".isEmpty()); //true
    }
}

3.2 获取功能

获取当前字符串对象中,包含的字符个数 "abcd"
int length()  
    
获取字符串对象代表字符序列中,指定位置的字符 从0开始"abcd"
char charAt(int index) 
    
在当前字符串对象中查找指定的字符,如果找到就返回字符,首次出现的位置,如果没找到返回-1
也可以填字符   "abcdb"
int indexOf(int ch) 
    
指定从当前字符串对象的指定位置开始,查找首次出现的指定字符的位置,(如果没找到返回-1)
可以填入字符
int indexOf(int ch,int fromIndex) 
    
查找当前字符串中,目标字符串首次出现的位置(如果包含),找不到,返回-1
这里的位置是指目标字符串的第一个字符,在当前字符串对象中的位置  "abcdefg"
int indexOf(String str) 

指定,从当前字符串对象的指定位置开始,查找首次出现的指定字符串的位置(如果没找到返回-1)
这里的位置是指目标字符串的第一个字符,在当前字符串对象中的位置
int indexOf(String str,int fromIndex) ,

返回字符串,该字符串只包含当前字符串中,从指定位置开始(包含指定位置字符)到结束的那部分字符串  "abcdef"
String substring(int start)   
    
返回字符串,只包含当前字符串中,从start位置开始(包含),到end(不包含)指定的位置的字符串  [ , )
String substring(int start,int end) 

3.3 转换功能

获取一个用来表示字符串对象字符序列的,字节数组
byte[] getBytes()
    
获取的是用来表示字符串对象字符序列的,字符数组
char[] toCharArray() 

    
把字符数组转换成字符串
static String valueOf(char[] chs)

把各种基本数据类型和对象转换成字符串  100---> "100"
static String valueOf(int i/double...)


把字符串全部转化为小写
String toLowerCase() 
    
把字符串全部转换为大写
String toUpperCase()

字符串拼接,作用等价于 + 实现的字符串拼接
String concat(String str) 
/**
 * @package: _01code._01string._03api
 * @description: 转换功能
 * @author: Yunyang
 * @date: 2023/10/30  14:36
 * @version:1.0
 **/
public class Demo3 {
    public static void main(String[] args) {
        // 获取一个用来表示字符串对象字符序列的,字节数组
        // byte[] getBytes()
        String s = "abcd";
        byte[] bytes = s.getBytes();
        System.out.println("bytes = " + Arrays.toString(bytes));
        // 获取的是用来表示字符串对象字符序列的,字符数组
        // char[] toCharArray()
        char[] chars = s.toCharArray();
        System.out.println("chars = " + Arrays.toString(chars));

        // 把字符数组转换成字符串
        // static String valueOf(char[] chs)
        String s1 = String.valueOf(chars);

        // 把各种基本数据类型和对象转换成字符串  100---> "100"
        // static String valueOf(int i/double...)
        String s2 = String.valueOf(100);// "100"
        String s3 = String.valueOf(3.14);// "3.14"
        String s4 = String.valueOf(true);//"true"
        // 把字符串全部转化为小写
        // String toLowerCase()

        // 把字符串全部转换为大写
        // String toUpperCase()
        String s5 = s.toUpperCase();
        System.out.println("s5 = " + s5);

        // 字符串拼接,作用等价于 + 实现的字符串拼接
        // String concat(String str)
        String concat = s.concat("ss");
        System.out.println("concat = " + concat);

    }
}

3.4 其他功能

String类的替换功能
在新的字符串中,用新(new)字符,替换旧(old)字符  "abcd" 
String replace(char old,char new)  

在新的字符串中,用新的字符串(new), 替换旧(old)字符串
String replace(String old, String new) 


在新的字符串中,去掉开头和结尾的空格字符 "abc"  "abc "
String trim()

分隔功能
将字符串按照符号分隔成字符串数组  "a,b,c,d"
String[] split(String re) 

String类的比较功能
int compareTo(String str)
int compareToIgnoreCase(String str)
/**
 * @package: _01code._01string._03api
 * @description: 其他功能
 * @author: Yunyang
 * @date: 2023/10/30  15:03
 * @version:1.0
 **/
public class Demo4 {
    public static void main(String[] args) {
        // String类的替换功能
        // 在新的字符串中,用新(new)字符,替换旧(old)字符  "abcd"
        // String replace(char old,char new)
        String s = "abcdef";
        String s1 = s.replace('a','A');
        System.out.println("s1 = " + s1);

        // 在新的字符串中,用新的字符串(new), 替换旧(old)字符串
        // String replace(String old, String new)
        String s2 = s.replace("ef", "yyds");
        System.out.println("s2 = " + s2);
        // 在新的字符串中,去掉开头和结尾的空格字符 "abc"  "abc "
        // // String trim()
        String s3 = " aBc ";
        System.out.println("s3.trim() = " + s3.trim());
        // // 分隔功能
        // // 将字符串按照符号分隔成字符串数组  "a,b,c,d"
        // // String[] split(String re)
        String s4 = "a,b,c,d";
        String[] split = s4.split(",");
        System.out.println(Arrays.toString(split));
        // // String类的比较功能
        // // int compareTo(String str)
        // // int compareToIgnoreCase(String str)
        String s5 = "ab";
        String s6 = "aB";
        //
        int i = s5.compareTo(s6);
        int j = s5.compareToIgnoreCase(s6);
        System.out.println("i = " + i);
        System.out.println("j = " + j);
    }
}

4 自然排序

4.1 Comparable接口

此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法

实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序

  • 实现此接口的类,其对象数组(array)或对象容器(collection)

    • 就可以通过**Arrays.sort()Collections.sort()**进行自动排序
  • 对于实现该接口的A类来说,其对象a1.compareTo(a2)方法返回值

    • 小于0,表示a1对象小于a2,在自然排序中处于前面的位置
    • 大于0,表示a1对象大于a2,在自然排序中处于后面的位置
    • 等于0,表示a1对象等于a2
      自定义类实现自然排序:
  • 实现Comparable接口

  • 重写compareTo方法

/**
 * @package: _01code._01string._04sort
 * @description:
 * @author: Yunyang
 * @date: 2023/10/30  16:11
 * @version:1.0
 **/
/*
* 练习:
定义一个学生类,让其按照学生的年龄的大小,从小到大进行排序
*/
public class Demo2 {
    public static void main(String[] args) {
        // 待排序数组
        Student[] students = new Student[5];
        students[0] = new Student("zs", 21, 66);
        students[1] = new Student("ls", 20, 77);
        students[2] = new Student("ww", 19, 99);
        students[3] = new Student("zl", 28, 88);
        students[4] = new Student("kun", 21, 59);

        System.out.println("排序前:" + Arrays.toString(students));
        //排序 sort方法
        Arrays.sort(students);

        System.out.println("排序后:" + Arrays.toString(students));
    }
}

/*
自定义类实现自然排序:

- 实现Comparable接口
- 重写compareTo方法
 */
class Student implements Comparable<Student> {
    String name;

    int age;

    int score;

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        //比较规则
        //按照年龄从小到大排序
        // return this.age - o.age;


        // 默认排序
        // 年龄相同的情况下,按照分数从高到低排序
        if (this.age == o.age) {
            return o.score - this.score;
        }

        // // 按照年龄从大到小排序
        return o.age - this.age;


    }
}

4.2 Comparator接口

在排序时需要注意一个比较特殊的方法,带比较器的Arrays.sort方法,
即sort(T[] a, Comparator<? super T> c)
根据指定比较器产生的顺序对指定对象数组进行排序。其中Comparator接口的实现类对象就是比较器,该对象通过compare方法传入比较的规则

表示传入比较规则的int compare(T o1, T o2)方法:
该方法可以看成是o1-o2,如果方法返回负数,o1< o2,相反则大于,只有当方法返回0时,才表示对象相等

三种方式去实现自然排序:

  • 手写接口类实现
  • 匿名内部类
  • lambda表达式
/**
 * @package: _01code._01string._04sort
 * @description:
 * @author: Yunyang
 * @date: 2023/10/30  16:33
 * @version:1.0
 **/
/*
* - 手写接口类实现
- 匿名内部类
- lambda表达式
*/
public class Demo3 {
    public static void main(String[] args) {
        // 创建学生对象
        Student2 s1 = new Student2("zs", 20, 99);
        Student2 s2 = new Student2("ls", 18, 98);
        Student2 s3 = new Student2("ww", 19, 89);
        Student2 s4 = new Student2("zl", 22, 95);
        Student2 s5 = new Student2("zsd", 17, 89);

        // 填充数组
        Student2[] student2s = {s1, s2, s3, s4, s5};
        // 排序前
        System.out.println("排序前:");
        System.out.println(Arrays.toString(student2s));

        // 排序 1.使用带比较器的sort方法
        // Arrays.sort(student2s,new MyComparator());

        //2.匿名内部类
        // Arrays.sort(student2s, new Comparator<Student2>() {
        //     @Override
        //     public int compare(Student2 o1, Student2 o2) {
        //         return o1.getScore() - o2.getScore();
        //     }
        // });
        
        //3.lambda表达式
        Arrays.sort(student2s, (stu1, stu2) -> stu1.getScore() - stu2.getScore());

        // 排序后
        System.out.println("排序后:");
        System.out.println(Arrays.toString(student2s));
    }
}

class Student2 {
    String name;

    int age;

    int score;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public int getScore() {
        return score;
    }

    @Override
    public String toString() {
        return "Student2{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }


}

// //手写实现类
// class MyComparator implements Comparator<Student2>{
//
//     @Override
//     public int compare(Student2 o1, Student2 o2) {
//         // 按照年龄从小到大排序
//         return o1.getAge() - o2.getAge();
//     }
// }

4 可变长字符串

4.1 StringBuffer构造方法

public StringBuffer() // 默认容量是16
public StringBuffer(int capacity)// 容量是capacity
public StringBuffer(String str)// str的长度+16

/**
 * @package: _01code._01string._05stringbuffer._02basic
 * @description:
 * @author: Yunyang
 * @date: 2023/10/30  17:13
 * @version:1.0
 **/
public class Demo {
    public static void main(String[] args) {
        // public StringBuffer() // 默认容量是16
        StringBuffer sb1 = new StringBuffer();
        // public StringBuffer(int capacity)// 容量是capacity
        StringBuffer sb2 = new StringBuffer(20);
        // public StringBuffer(String str)// str的长度+16
        StringBuffer sb3 = new StringBuffer("abc");
        System.out.println(sb3);
    }
}

4.2 StringBuffer成员方法

获取功能
public int capacity() 返回当前容量,数组的长度,理论值
public int length() 返回长度(字符的个数),实际值
添加功能
public StringBuffer append(String s) 将指定的字符串(其他类型有重载方法)追加到此字符序列的尾部
在指定位置把任意类型的数据插入到字符串缓冲区里面
public StringBuffer insert(int offset,String str)
删除功能
public StringBuffer deleteCharAt(int index):删除指定位置的字符
public StringBuffer delete(int start,int end):删除从指定位置开始指定位置结束的内容
替换功能
使用给定String中的字符替换词序列的子字符串中的字符
public StringBuffer replace(int start,int end,String str)
反转功能
public StringBuffer reverse():将此字符序列用其反转形式取代,返回对象本身

/**
 * @package: _01code._01string._05stringbuffer._02basic
 * @description:
 * @author: Yunyang
 * @date: 2023/10/30  17:17
 * @version:1.0
 **/
public class Demo2 {
    public static void main(String[] args) {
        // 获取功能
        // public int capacity() 返回当前容量,数组的长度,理论值
        StringBuffer sb = new StringBuffer();
        System.out.println("sb.capacity() = " + sb.capacity());

        // public int length() 返回长度(字符的个数),实际值
        System.out.println("sb.length() = " + sb.length());


        // 添加功能
        // public StringBuffer append(String s) 将指定的字符串(其他类型有重载方法)追加到此字符序列的尾部
        StringBuffer sb2 = sb.append("Hello");
        System.out.println("sb2 = " + sb2);

        // 在指定位置把任意类型的数据插入到字符串缓冲区里面
        // public StringBuffer insert(int offset,String str)
        StringBuffer sb3 = sb.insert(5, "World");
        System.out.println("sb3 = " + sb3);

        // 删除功能
        // public StringBuffer deleteCharAt(int index):删除指定位置的字符
        StringBuffer sb4 = sb3.deleteCharAt(0);
        System.out.println("sb4 = " + sb4);


        // public StringBuffer delete(int start,int end):删除从指定位置开始指定位置结束的内容
        StringBuffer sb5 = sb3.delete(0,4);
        System.out.println("sb5 = " + sb5);
        // 替换功能
        // 使用给定String中的字符替换词序列的子字符串中的字符
        // public StringBuffer replace(int start,int end,String str)

        StringBuffer sb6 = sb3.replace(5, 9, "Cat");

        System.out.println("sb6 = " + sb6);
        // 反转功能
        // public StringBuffer reverse():将此字符序列用其反转形式取代,返回对象本身
        StringBuffer sb7 = sb6.reverse();
        System.out.println("sb7 = " + sb7);
    }
}

4.3 常见问题

String, StringBuffer之间的相互转换

/**
 * @package: _01code._01string._05stringbuffer._02basic
 * @description:
 * @author: Yunyang
 * @date: 2023/10/30  17:21
 * @version:1.0
 **/
public class Demo3 {
    public static void main(String[] args) {
        String s = "abc";
        //String--->StringBuffer
        //利用构造方法
        StringBuffer sb = new StringBuffer(s);
        System.out.println("sb = " + sb);
        //StringBuffer--->String
        //利用toString方法
        String s1 = sb.toString();
        System.out.println("s1 = " + s1);
        System.out.println(Integer.MAX_VALUE+1);
        System.out.println(Byte.MAX_VALUE+1);

    }
}

String, StringBuffer和StringBuilder有啥区别

StringBuffer和StringBuilder从效率上来说哪个更快?

image-20221014102227298- 和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改

  • 并且不产生新的未使用对象,不会产生效率问题和空间浪费问题
  • StringBuffer是线程安全的,StringBuilder是线程不安全的
    • StringBuilder的效率会比StringBuffer效率更高,单线程的程序推荐使用StringBuilder
    • 在多线程的程序中,应该优先考虑使用StringBuffer,安全性要更重要
    • 它们的效率都比String高很多
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值