JAVA核心技术笔记

1 JAVA基本程序设计

1.1 JAVA有几种注释方法?
答:3种

(1)///  单行注释
(2)/* */   多行注释
(3) /**  */  可以用来自动生成文档  

1.2 JAVA有几种数据类型?
答:2大类,基本数据类型和引用数据类型
8种基本数据类型,其中4种整数型,2种浮点数,1种字符串类型,1种boolean类型

基本数据类型
int   		4个字节
short		2字节
long		8字节
byte		1字节
float		4字节
double		8字节
char		2字节
boolean

这八种基本类型都有对应的包装类分别为:
Byte、Short、Integer、Long、
Float、Double、Character、Boolean 。

引用数据类型:
数组
类
接口
枚举
注解
引用类型的数据创建对象时需要通过关键字 new 创建对象
什么是自动拆装箱?

装箱:将基本类型用它们对应的引用类型包装起来;
拆箱:将包装类型转换为基本数据类型;

Integer i = 10;  //装箱
int n = i;   //拆箱

包装类型的常量池技术

Java 基本类型的包装类的大部分都实现了常量池技术。

Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False。
两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。

int int1 = 12;
int int2 = 12;

Integer integer1 = new Integer(12);
Integer integer2 = new Integer(12);
Integer integer3 = new Integer(127);
		
Integer a1 = 127;
Integer a2 = 127;
		
Integer a = 128;
Integer b = 128;

int1 == int2 -> true
 int1 == integer1 -> true
integer1 == integer2 -> false
integer3 == a1 -> false
a1 == a2 -> true
a == b -> false

Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);	//true
字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建。
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
System.out.println(aa==bb);// true

1.3 break和continue和return的区别?
答:

continue :指跳出当前的这一次循环,继续下一次循环。
break :指跳出整个循环体,继续执行循环下面的语句。
return 用于跳出所在方法,结束该方法的运行。

1.4数组的定义方式

声明数组方式:
int[] a;
或者
int a[];
以上方法只是声明了数组,并没有初始化

初始化数组:
int[] a= new int[100];  //创建了长度为100的数组,创建后长度不可改变
int a[]={1,2,3,4,5};	//创建了数组对象并提供初始值

多维数组:
int[][] a=	{{1,2,3,4},
			{2,3,4,5}}
			
//定义一个整型数组:3行4列
int a[][] = new int[3][4];
//获取行数---3行
int lenY = a.length;
//获取列数---4列
int lenX = a[0].length;

1.5== 和 equals() 的区别

对于基本数据类型来说,== 比较的是值。
对于引用数据类型来说,== 比较的是对象的内存地址。

equals() 不能用于判断基本数据类型的变量,
只能用来判断两个对象是否相等。

String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
System.out.println(aa == bb);// true
System.out.println(a == b);// false
System.out.println(a.equals(b));// true
System.out.println(42 == 42.0);// true

hashCode() 和equals()重写

https://blog.csdn.net/wonad12/article/details/78958411?ops_request_misc=&request_id=&biz_id=102&utm_term=hashCode()%20%E5%92%8C%20equals()&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3-78958411.142^v5^article_score_rank,157^v4^control&spm=1018.2226.3001.4187

https://blog.csdn.net/u012557538/article/details/89861552?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164906509316782094886790%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164906509316782094886790&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-7-89861552.142^v5^article_score_rank,157^v4^control&utm_term=hashCode%28%29+%E5%92%8C+equals%28%29&spm=1018.2226.3001.4187

2对象与类
2.1类的定义方式?

public class ClassName {
//成员变量
//成员方法
}

2.2对象的构造方式以及访问类的成员

类名 对象名 = new 类名();
对象名.成员变量;
对象名.成员方法();


java创建对象时最后那个小括号是什么意思?
答:new后面的是一个整体,是构造方法
作为构造函数用来实例化,如果构造函数有参数就传入相对的参数,没有就不传留个"()"

例子:

public class Foo{
        public int i;
        public String s;
 
public Foo(){//无参构造函数
                i = 9;
                s = "abc";
        }
 
public Foo(String a){//有参构造函数
                i = 9;
                s = a;
        }
}
Foo f1 = new Foo(); Foo f2 = new Foo("haha");

2.3成员变量与局部变量的区别

成员变量:类中,方法外,有默认值
局部变量:方法中,必须先定义赋值

语法形式 :从语法形式上看,成员变量是属于类的,
而局部变量是在代码块或方法中定义的变量或是方法的参数;
成员变量可以被 public,private,static 等修饰符所修饰,
而局部变量不能被访问控制修饰符及 static 所修饰;
但是,成员变量和局部变量都能被 final 所修饰。

存储方式 :从变量在内存中的存储方式来看,
如果成员变量是使用 static 修饰的,那么这个成员变量是属于类的,
如果没有使用 static 修饰,这个成员变量是属于实例的。
而对象存在于堆内存,局部变量则存在于栈内存。

生存时间 :从变量在内存中的生存时间上看,成员变量是对象的一部分,
它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。

默认值 :从变量是否有默认值来看,成员变量如果没有被赋初始值,
则会自动以类型的默认值而赋值(
一种情况例外:被 final 修饰的成员变量也必须显式地赋值),
而局部变量则不会自动赋值。

2.4一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗?

构造方法主要作用是完成对类对象的初始化工作。 
如果一个类没有声明构造方法,也可以执行!
因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。
如果我们自己添加了类的构造方法(无论是否有参),
Java 就不会再添加默认的无参数的构造方法了,
这时候,就不能直接 new 一个对象而不传递参数了,
所以我们一直在不知不觉地使用构造方法,
这也是为什么我们在创建对象的时候后面要加一个括号
(因为要调用无参的构造方法)。
如果我们重载了有参的构造方法,
记得都要把无参的构造方法也写出来(无论是否用到),
因为这可以帮助我们在创建对象的时候少踩坑。

2.5构造方法有哪些特点?是否可被 override?

构造方法特点如下: 名字与类名相同。 没有返回值,
但不能用 void 声明构造函数。 
生成类的对象时自动执行,无需调用。 
构造方法不能被 override(重写),
但是可以 overload(重载),
所以你可以看到一个类中有多个构造函数的情况。

2.6面向对象的三大特征:封装、继承、多态

封装:
将类的某些信息隐藏在类内部,不允许外部程序直接访问,
而是通过该类提供的方法来实现对隐藏信息的操作和访问
成员变量private,提供对应的getXxx()/setXxx()方法

通过方法来控制成员变量的操作,提高了代码的安全性
把代码用方法进行封装,提高了代码的复用性


public class Student {
    private int id;//id属性私有化
    private String name;//name属性私有化

    //获取id的方法
    public int getId() {
        return id;
    }

    //设置id的方法
    public void setId(int id) {
        this.id = id;
    }

    //获取name的方法
    public String getName() {
        return name;
    }

    //设置name的方法
    public void setName(String name) {
        this.name = name;
    }
}
继承:

多态:
多态体现为父类引用变量可以指向子类对象。
前提条件:必须有子父类关系。

接口详解

https://blog.csdn.net/weixin_38568503/article/details/112251386?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164750750016782248544583%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164750750016782248544583&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-4-112251386.142^v2^article_score_rank,143^v4^control&utm_term=java+%E6%8E%A5%E5%8F%A3&spm=1018.2226.3001.4187

接口和抽象类有什么共同点和区别?

接口中包括:
1.public stattic final 常量
2.抽象方法
3.静态方法
4.默认方法
接口实现类必须重写实现接口的所有抽象方法
接口继承接口使用extend ,接口实现类继承接口使用implements

抽象类中包括:
1.常量
2.变量
3.可以有抽象方法或非抽象方法

共同点 :

都不能被实例化。
都可以包含抽象方法。
都可以有默认实现的方法(Java 8 可以用 default 关键在接口中定义默认方法)。

区别 :
接口主要用于对类的行为进行约束,你实现了某个接口就具有了对应的行为。
抽象类主要用于代码复用,强调的是所属关系(比如说我们抽象了一个发送短信的抽象类,)。
一个类只能继承一个类,但是可以实现多个接口。
接口中的成员变量只能是 public static final 类型的,不能被修改且必须有初始值,
而抽象类的成员变量默认 default,可在子类中被重新定义,也可被重新赋值。

重写与重载

重写:
从字面上看,重写就是 重新写一遍的意思。
其实就是在子类中把父类本身有的方法重新写一遍。
子类继承了父类原有的方法,但有时子类并不想原封不动的继承父类中的某个方法,
所以在方法名,参数列表,返回类型(除过子类中方法的返回值是父类中方法返回值的子类时)都相同的情况下, 对方法体进行修改或重写,这就是重写。
但要注意子类函数的访问修饰权限不能少于父类的。

重写有以下三个限制:
1.子类方法的访问权限必须大于等于父类方法;
2.子类方法的返回类型必须是父类方法返回类型或为其子类型。
3.子类方法抛出的异常类型必须是父类抛出异常类型或为其子类型。
使用 @Override 注解,可以让编译器帮忙检查是否满足上面的三个限制条件。

重载:
存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。
应该注意的是,返回值不同,其它都相同不算是重载。
重载方法的优先级,char->int->long->float->double ->Character -> Serializable -> Object ,基本类型的重载方法会按此优先级寻找对应的方法,若重载的方法参数与调用的方法不一致,则会向父类查找匹配上相同类型的方法。

1.重载Overload是一个类中多态性的一种表现
2.重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序)
3.重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准

总结:
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
重写
public class Father {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Son s = new Son();
        s.sayHello();
    }
    public void sayHello() {
        System.out.println("Hello");
    }
}

class Son extends Father{
    @Override
    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("hello by ");
    }
}
重载
public class Father {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Father s = new Father();
        s.sayHello();
        s.sayHello("wintershii");

    }

    public void sayHello() {
        System.out.println("Hello");
    }

    public void sayHello(String name) {
        System.out.println("Hello" + " " + name);
    }
}

JAVA中的关键字:
java种的关键字
This和Super

一、Java当中this和super的区别:
1.属性的区别:
     (1)this访问本类中的属性,如果本类没有这个属性则访问父类中的属性。
     (2)super访问父类中的属性。 
2.方法的区别:
     (1)this访问本类中的方法,如果本类没有这个方法则访问父类中的方法。
     (2)super访问父类中的方法。 
3.构造的区别:
     (1)this调用本类构造构造,必须放在构造方法的首行。
     (2)super调用父类构造,必须放在子类构造方法首行。 
     (3)其他区别:this表示当前对象。super不能表示当前对象 
 
二、this. 变量和super.变量
     (1)this.变量:调用的当前对象的变量; 
     (2)super.变量:直接调用的是父类中的变量。 
 
三、this(参数)super(参数)方法 
     (1this(参数):调用(转发)的是当前类中的构造器; 
     (2super(参数):用于确认要使用父类中的哪一个构造器。
 
四、注意点: 
     (1)在对拥有父类的子类进行初始化时,父类的构造方法也会执行,且优先于子类的构造函数执行;因为每一个子类的构造函数中的第一行都有一条默认的隐式语句super();2this()super()都只能写在构造函数的第一行; 
     (3this()super() 不能存在于同一个构造函数中。
            1this()super()都必须写在构造函数的第一行;
            2this()语句调用的是当前类的另一个构造函数而这个另一个构造函数中必然有一个父类的构造器,再使用super()又调用一次父类的构造器, 就相当于调用了两次父类的构造器,编译器不会通过; 
     (4)this和super不能用于static修饰的变量,方法,代码块;因为this和super都是指的是对象(实例)。
https://blog.csdn.net/lzm18064126848/article/details/47068589?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164726070216780264058010%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164726070216780264058010&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-47068589.142^v2^article_score_rank,143^v4^control&utm_term=this+super&spm=1018.2226.3001.4187

静态方法与实例方法的区别

在外部调用静态方法时,可以使用 类名.方法名 的方式,也可以使用 对象.方法名 的方式,而实例方法只有后面这种方式。
也就是说,调用静态方法可以无需创建对象。(静态方法和静态对象可以直接通过类访问)

不过,需要注意的是一般不建议使用 对象.方法名 的方式来调用静态方法。
这种方式非常容易造成混淆,静态方法不属于类的某个对象而是属于这个类。

因此,一般建议使用 类名.方法名 的方式来调用静态方法。

静态方法为什么不能调用非静态成员?

静态方法是属于类的,在类加载的时候就会分配内存,可以通过类名直接访问。
而非静态成员属于实例对象,只有在对象实例化之后才存在,需要通过类的实例对象去访问。
在类的非静态成员不存在的时候静态成员就已经存在了,此时调用在内存中还不存在的非静态成员,属于非法操作。

静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),
不允许访问实例成员(即实例成员变量和实例方法),而实例方法不存在这个限制。

类、方法、变量修饰符和变量引用

1.final
数据:声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能被改变的常量。
对于基本类型,final 使数值不变;
对于引用类型,final 使引用不变,也就不能引用其它对象,但是被引用的对象本身是可以修改的。

方法:声明方法不能被子类重写。
private 方法隐式地被指定为 final,如果在子类中定义的方法和基类中的一个 private 方法签名相同,此时子类的方法不是重写基类方法,而是在子类中定义了一个新的方法。

类:声明类不允许被继承。

2.static
静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过 类名 来访问它。静态变量在内存中只存在一份。

静态方法:静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法。
只能访问所属类的静态字段和静态方法,方法中不能有 this 和 super 关键字,这两个关键字与具体对象关联

静态语句块:静态语句块在类初始化时运行一次。

静态内部类:非静态内部类依赖于外部类的实例,也就是说需要先创建外部类实例,才能用这个实例去创建非静态内部类。而静态内部类不需要。

3.abstract
如果一个类中包含抽象方法,那么这个类必须声明为抽象类。
抽象类和抽象方法都使用 abstract 关键字进行声明。
抽象类和普通类最大的区别是,抽象类不能被实例化,只能被继承。
静态变量
https://blog.csdn.net/weixin_44774713/article/details/122307676?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164906437816780269834412%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164906437816780269834412&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-4-122307676.142^v5^article_score_rank,157^v4^control&utm_term=java%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F&spm=1018.2226.3001.4187

访问控制(权限修饰符):
在这里插入图片描述

JAVA集合

Collection 接口的接口 对象的集合(单列集合)
├——-List 接口:元素按进入先后有序保存,可重复
│—————-├ LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全
│—————-├ ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全
│—————-└ Vector 接口实现类 数组, 同步, 线程安全
│ ———————-└ Stack 是Vector类的实现类
└——-Set 接口: 仅接收一次,不可重复,并做内部排序
├—————-└HashSet 使用hash表(数组)存储元素
│————————└ LinkedHashSet 链表维护元素的插入次序
└ —————-TreeSet 底层实现为二叉树,元素排好序

Map 接口 键值对的集合 (双列集合)(map没有继承collection)
├———Hashtable 接口实现类, 同步, 线程安全
├———HashMap 接口实现类 ,没有同步, 线程不安全-
│—————–├ LinkedHashMap 双向链表和哈希表实现
│—————–└ WeakHashMap
├ ——–TreeMap 红黑树对所有的key进行排序
└———IdentifyHashMap

在这里插入图片描述

List  :有ArrayList和LinkList,存放的数据可以重复
ArrayList(线程不安全):数组方式实现
LinkList(线程不安全):双端链表方式实现

优点:
1、支持自动改变大小
2、可以灵活的插入元素,可以插入null
3、可以灵活的删除元素
4.有序集合
局限:
比一般的数组的速度慢一些;
Set:有HashSet和TreeSet,存放的数据不可重复
HashSet:链表+数组实现
TreeSet:二叉树实现
Map:有HashMap和TreeMap,存放两列,分别为key和value
Hashmap
TreeMap

hashmap由链表节点的数组组成,节点包括key,value,hash,next
size:存储节点的个数(不一定等于数组的长度)
负载因子:0.75
容量:数组长度
扩容阈值=容量*负载因子
当size>扩容阈值,容量扩容一倍,初始容量为16
当链表长度达到8 AND 数组容量大于等于64,转为红黑树
hashcode()返回对象的内存地址

HashaMap基本操作:
HashMap<Integer,Integer> map = new HashMap<>();

map.size()	//长度
map.put(key,value)  //添加key和value,如果key存在,则覆盖原有的value
map.remove(key) //删除key和key对应的value
map.get(key)	//获取key所对应的value
map.getOrDefault(key,自定义值)	//若表中存在key,则返回对应的value,不存在,则返回自定义值
map.getOrDefault("aa",-1)//key=aa不存在,所以返回默认value -1
map.containsKey("aa")	//判断key是否存在
map.containsValue(1)	//判断value是否存在
map.replace(key,value)	//若表中存在key,则替换,若不存在,则不操作

queue	//队列

stack	//栈
Stack<类型> stack =new Stack<类型>()
基本操作:
push( num) //入栈
pop() //栈顶元素出栈
empty() //判定栈是否为空
peek() //获取栈顶元素
search(num) //判端元素num是否在栈中,如果在返回1,不在返回-1。

String

引用类型
String分为string字符串和string数组
 string字符串,例如String a=“12354”
a.length=5	a.charAt(1)=2   //charAt 取出下标对应的值,返回char类型

//string数组创建
String arr[] = new String[10]; //创建一个长度为10的String 类型数组。 
String arr[] = {"张三","李四"}; 
String[] str = new String[]{"","","","",""};

 string数组,例如String[] b= {"123","13156"}
 b.length=2
 b[1]="13156"
 b[1].length=5

substring()的作用就是截取父字符串的某一部分
public String substring(int beginIndex, int endIndex)
第一个参数int为开始的索引,对应String数字中的开始位置,
第二个参数是截止的索引位置,对应String中的结束位置

String、StringBuffer、StringBuilder的区别
String:值不可变,内容不可修改,效率低,每次对其操作会产生新的对象
StringBuffer:可以修改,线程安全,多线程操作字符串
StringBuilder:可以修改,线程不安全,单线程操作字符串,运行速度最快

速度:StringBuilder > StringBuffer > String

String为什么是不可变?
String类是不可变的对象,即创建后的对象不可改变
例如:
String s = "ABCabc";
System.out.println("s = " + s);
s = "123456";
System.out.println("s = " + s);
打印结果:
s = ABCabc
s = 123456

对象:"ABCabc",s只是一个引用,修改后s指向了另一个对象 "123456"的地址,每次操作都是生成一个新的对象

String,char,char[]的相互转换:
1.char转string
char c= 'c';
String s= Character.toString(c);
String s1=String.valueOf(c);
String s2= ""+'c';

2.char[]转String
char[] c={'a','b','c'};
String s1= new String(c);
String s2= String.valueOf(c);
String s3 =Arrays.toString(c);

char与string区别
char只能存放单个字符,且不能更改,char[]可以存放单个的字符数组(与int[]一样),
string可以存放多个字符,但是不可修改,因此一般使用stringBuild修改字符

3.String转char[]
String s="abc";
char[] c=s.toCharArray();

用法:
https://blog.csdn.net/xhjj520/article/details/78486895?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164631599116780264018900%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164631599116780264018900&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-78486895.pc_search_insert_es_download&utm_term=java+string%E7%94%A8%E6%B3%95&spm=1018.2226.3001.4187

length的用法

数组.length		属性
字符串.length()	方法
集合.size()		方法
都是返回int

JAVA包装类

1.character
.isLetter('a')			//判断是不是字母
.isDigit('3')			//判断是不是数字
.isLetterOrDigit('s')	//判断是不是字母或数字
.isWhitespace('\t')		//判断是不是空格
.isUpperCase('a')		//判断是不是大写
.isLowerCase('b')		//判断是不是小写
.toUpterCase('a')		//指定为大写,若不是英文转为原字符
.toLowerCase('A')		//指定为小写,若不是英文转为原字符
.toString('a')			//转为字符串
.hashCode('a')			//返回当前字符的哈希表码
.getNumericValue('a')	//返回字符ch的数值
void与return

如果方法没有return,则需要填void
public void A(int a){ a=10; }

如果方法有return,则需要填对应的类型
public int B(int a){ a=10; return a;}

public static void main(String[] args) {
        int a=1;
       调用A,调用B
    }

没有返回值的方法,没有改变 a 的值;
有返回值的方法, 改变了 a 的值。
没有返回值的 change() 方法,只是在调用方法时,在方法中 a 的值进行过修改操作,然而并没有将结果存储到方法外。
有返回值的 change1()方法,操作完成后,将结果返回到了a的存储位置,使得结果发生改变。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值