Java/数据库方面常见问题

==和equals的区别?

  1. == 比较基本类型是比较值, 强类型是比较引用

  2. 基本类型只能用==, 没有equals方法

  3. 强类型的equals方法默认是继承自Object类的,该方法默认和==一样,比较引用。

    如果重写后,按重写后的比较。

  4. java规定如果重写equals方法,那么也推荐一并重写hashcode方法,保证对象相等的情况下,hashcode也要相等. (PS:hashcode相等不一定equals相等,因为会有hash冲突的情况)否则会造成使用HashMap,HashSet对象的时候出现错误。

String和StringBuilder,StringBuffer的区别 ?

  • String底层是不可变的类,所以每次赋值都会重新创建新的对象

    所以如果要频繁的修改字符串的值,不推荐使用String。

    应该使用StringBuffer或StringBuilder替代。

    当考虑线程安全的情况下使用StringBuffer

    不考虑线程安全的情况下使用StringBuilder效率更高

Static关键字的作用 ?

  • static可以修饰 内部类,静态导包,属性,方法

  • static修饰的属性和方法可以使用类名和对象访问,但是推荐使用类名访问,不论使用什么访问,都是访问的同一个内存空间,只有一份。

  • 被static修饰的属性和方法属于类,不属于具体的对象。

    所以static是共享的,建议在static属性上添加final只读,否则多处修改会造成数据安全的问题。

  • 由于是类的属性和方法,所以存放在方法区中,除非卸载类,否则GC不予回收,所以不能够什么都去用static修饰方法。一般在工具类中的方法考虑添加static。

方法重载 

  • 构造器和实例方法和类方法都可以重载

  • 重载是在本类中,要求:1. 方法名相同 2. 参数列表不同(个数,类型)

  • 与其他方法签名部分无关

方法重写 

  • 重写是发生在子类和父类关系中的,子类重写/覆盖父类的方法

  • 方法名相同

  • 参数列表相同

  • 访问修饰符要比父类的更宽泛(大),或者一样

  • 返回值要一样或者是父类返回值的派生类

  • 抛出的异常不可以比父类的更宽泛(大)

final的作用 

  1. final可以修饰类, 代表最终类,不可被继承

  2. final可以修饰方法,代表最终方法, 不可被重写覆盖。故抽象方法不可以添加final

  3. final可以修饰属性,代表常量,值不可变,需要区别的是:

    • 基本类型: 值不可变

    • 引用类型: 变量的引用值不可变,但其内部的属性是可以变的

异常的理解 

  1. java的异常的基类是Throwable,其下有两个子类,分为Exception(异常)和Error(错误)

  2. Error代表错误,一般程序无法处理和修复

  3. Exception代表异常,其下又会分为两大类异常。

    • 检查性异常,一般称为checked异常,这类异常都继承自Exception类(RuntimeException除外)

    • 非检查性异常,一般称为unchecked异常,这类异常都继承自RuntimeException

  4. 检查性异常要求程序必须显示处理的异常

  5. 非检查性异常系统不做要求,程序可自行选择是否添加处理代码

线性存储和链式存储的区别 ?

  1. java中线性存储的数据结构有: 数组,ArrayList

    它们的优点是:查找访问快.缺点是在非末尾的位置删除和插入效率低.

  2. java中链式/表存储的数据结构有:LinkedList

    它们的优点是:插入和删除效率高.缺点是访问非头尾的位置效率低.

常用数据结构的理解 ?

  • ArrayList和LinkedList实现自List接口,基类接口为Collection

  • HashSet和TreeSet实现自Set接口,基类接口为Collection

  • ArrayList和LinkedList有序,可重复

  • HashSet无序,不可重复

  • TreeSet排序(存放的排序数据需要实现Comparable接口),不可重复

HashMap底层实现原理 ?

  1. HashMap底层是由数组+链表+红黑树实现

  2. put 原理

    • 根据key计算hash,找到要存储的数组位置

    • 如果该位置为null,直接存储进去

    • 如果不为null,判断key的equals是否相等,如果相等则覆盖并返回旧的值,

      如果key不相等,那么会把新的数据以链表格式存储到该位置的末尾。

      当该链表的长度超过8的时候,会转换成红黑树(因为链表的长度太长查找效率没有红黑树高效)。

  3. get 原理

    • 根据key计算hash,找到要获取数据的位置

    • 判断该位置是否为null,为null返回null

    • 不为null,循环链表或红黑树逐个判断equals是否相等,相等返回值,没找到

      返回null。

  4. 扩容,默认hashmap底层大小为16, 扩容因子0.75,每次扩容2倍。

JVM内存模型(压轴落幕)

  • 共享部分

    1. 堆(heap)

      • new出来的对象

    2. 方法区 / 元空间

      • 常量池

      • 静态属性

      • 类的元数据

  • 独享部分

    1. 栈 / 虚拟机栈 stack

      • 局部变量表

      • 操作数栈

      • 静态链接 / 动态链接

      • 方法出口

    2. 本地方法栈 stack 存放的都是native的方法,内部结构和虚拟机栈类似。

    3. 程序计数器

      • 记录线程执行的位置

      • 该位置是jvm中唯一不可能出现内存溢出或泄露的位置

位或 |,位与 &, 位异或 ^, 位非 ~ 运算符 **

  • 这些运算都要把十进制转换为二进制

  • | 只有有1就为1, 否则就为0

  • & 两个数都为1就为1, 否则就为0

  • ^ 两个数相同则为0, 不同则为1

  • ~ 二进制取反, 0为1, 1为0。 以十进制为例: ~100=-101 -101=100

IO流 

  • IO流分为 输入流InputStream和输出流OutputStream

  • 输入流和输出流又分为 字节流和字符流

  • 字符流的底层也为字节流

  • 操作文件的时候使用字节流,操作字符的时候使用字符流

什么是缓冲区 ?

  • 缓冲区分为输入缓冲区和输出缓冲区,

  • 输入缓冲区:一次从磁盘中读取足够大的数据到缓冲区内存中

    程序后续每次从缓冲区内存中读取一定量的数据,用于减少读取磁盘次数

  • 输出缓冲区:每次把数据写到缓冲区内存中,当缓冲区内存数据量

    达到一定量的时候,一次性写入磁盘,用于减少写入磁盘的次数

字节流和字符流转换 

  • InputStreamReader

  • OutputStreamWriter

对象的创建有哪些方式

  1. new(会执行构造器)

  2. 反序列化(Serializable不会执行构造,Externalizable会执行构造)

  3. 克隆(因为clone走的是本地native方法,所以是第三方平台库创建的对象,不会执行java的构造器)

  4. 反射(会执行构造器)

什么是序列化和反序列化 ?

  1. 序列化就是把程序内存中的数据持久化到介质(硬盘)上的过程

  2. 反序列化是把介质(硬盘)上的持久化数据,反向读取到程序内存中

  3. 序列化需要实现Serializable接口

  4. 反序列化会对应程序的版本号,如果修改过代码导致版本号不一致,无法反序列化,

    会抛出InvalidClassException异常。

  5. transient和static修饰的属性无法被序列化

什么是深拷贝和浅拷贝 ?

  1. 浅拷贝是把对象中的数据的值直接拷贝到克隆的对象中去,被克隆的对象中的属性如果是基本数据类型,那么无影响,如果有引用类型,那么拷贝到新的对象中也是这个引用.所有后续如果对引用类型修改,会有牵连。

  2. 深拷贝则是把对象中引用类型的属性再去克隆新的地址,这样克隆出来的两个对象的属性完全隔离。

类的加载过程?

  1. 类加载器会把二进制class文件加载到方法区

  2. 验证: 确保字节码内部信息完整,没有被篡改

  3. 准备: 初始化类的信息,在方法区中为static的属性分配空间和默认值

  4. 解析: 解析类中的元数据,属性,类,接口是否引用错误

  5. 初始化: 执行static代码块,赋初值。

  6. 使用

  7. 最后卸载,手动卸载和jvm结束自动卸载

类加载器 

  1. AppClassLoader 应用程序加载器,负责加载用户自定义的类

  2. BootStrapClassLoader 启动类加载器,jvm启动的时候自动会调用底层平台的库,然后加载jre/lib中必备的jar。如我们常用的rt.jar。

  3. ExtClassLoader 扩展类加载器,负责加载jre/lib/ext目录下的jar库。

  4. 这三个类加载器的关系为:

    BootStrapClassLoader > ExtClassLoader > AppClassLoader

什么是双亲委派机制 ?

  • 当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。

  • 防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。

  • 保证核心.class不能被篡改,保证数据安全。

程序,进程,线程的关系 ?

  • 一个程序可以包含多个进程

  • 一个进程可以包含多个线程

  • 线程是程序执行的最小单元

多线程创建方式

  • 继承Thread类

  • 实现Runnable接口

  • 实现Callable接口

  • 线程池

多线程安全问题怎么解决?

  1. 多实例,缺点: 浪费空间

  2. 添加synchronize关键字,缺点: 效率低,逐个线程排队执行

  3. 使用本地线程ThreadLocal

  4. 使用Lock锁,缺点: 效率低,逐个线程排队执行

  5. 使用局部变量,因为局部变量不存在线程安全的问题。

    缺点是:多线程的时候不一定具备这种场景

volatile关键字的作用,能保证线程安全吗 ?

  1. 保证线程获取的数据是最新值

  2. 防止指令的重排序

  3. 无法保证线程的安全性

线程的状态

  1. 新建

  2. 就绪

  3. 运行

  4. 等待 / 阻塞

  5. 死亡

你知道哪些锁

  1. 可重入锁和不可重入锁

  2. 可重入锁可能导致死锁

    • 死锁有四大条件

    • 互斥、占用且等待新资源、不可抢占、循环等待

    • 解决死锁打破四个条件之一即可

    • 比如我常用的方式是如果有可重入锁的情况,尽量保证多个位置按相同锁的顺序加锁

  3. 排它锁

    • 获取到排它锁后,其他线程无法获取共享锁读取数据也无法获取排它锁写入数据

  4. 共享锁

    • 获取到共享锁后,其他线程可以再次获取共享锁同时读取数据,但不可以获取排它锁进行修改数据

sleep和yield和wait区别

  1. sleep和yield都属于Thread类的静态本地方法

  2. sleep和yield都不会释放对象锁

  3. sleep是等待固定时间后进入就绪态

  4. yield是直接从运行退让到就绪态(给其他线程空出机会)

  5. wait是Object的方法

  6. wait是进入等待状态,并且释放当前线程占用的对象锁(synchronized)

interrupt和stop的区别 ?

  1. 使用stop或者interrupt 不推荐stop,因为强制停止,会造成线程方法直接中断,导致不可预期后果

  2. interrupt打断一个线程,不会直接强制停止我们的线程,

而是给一个标志, 线程方法中可以判断isInterrupted这个标志,然后自行结束线程.
  1. interrupt如果打断的是一个等待状态的线程,那么会收到一个

InterruptException异常,并且标志会被重置。

什么是反射 ?

  1. Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法

  2. 对于通用性的模块和功能,首先考虑使用反射。

TCP和UDP的区别

  1. TCP需要三次握手,面向连接,可靠机制保证数据不丢失且有序,但是效率不高

  2. UDP不可靠,无连接,适用于实时性较高,但对安全性较低的地方。

Finalize方法 ?

  1. Object的空方法,GC要回收哪个对象,就会提前调用哪个对象的该方法

  2. 该方法代表GC回收对象时,如果被回收的对象重写了该方法,那么回收该对象之前会先调用该方法(仅会调用一次)

垃圾回收区域 

  1. 首先程序员无法具体控制GC何时执行回收

  2. GC是Java的守护线程在后台运行,一般分为轻GC(majorGC)和重GC(fullGC)

  3. GC90%以上情况都是回收堆里面的新生代对象

  4. 当对象的年龄达到15(默认值,可以jvm参数修改),进入老年代。

  5. 老年代内存如果快满了,会执行fullGC。

  6. 堆中会划分为新生代-(内含Eden区,Survivor-from区和Survivor-to区,这2个区会来回互换,腾出一个给到下次回收使用,具体参考复制算法),老年代(老年代的对象都是年龄较大或比较大的对象)

GC算法 

  1. GC算法有: 引用计数法,可达性分析算法,标记清除,标记整理,复制,分代收集

  2. Java主流虚拟机都是通过可达性分析算法确定一个对象是否为垃圾对象

  3. 标记清除:造成内存碎片过多,不适合后续使用

  4. 复制算法:缺点是空间使用率低,因为要空出一半做复制。优点是效率高,不会有内存碎片

  5. 标记整理算法:优点是不会产生空间碎片,但是效率相对较低。

  6. 分代收集算法:在不同的区域使用不同的回收算法,如

    • 新生代一般采用复制算法,比如幸存者0区和1区的复制

    • 老年代一般采用标记整理算法,所以效率比较低,重GC会停止其他业务线程的使用

什么是强引用,软引用,弱引用,虚引用 ?

强引用 User user = new User()

软引用SoftReference<User> user = new SoftReference<>(new User());

弱引用WeakReference<User> user = new WeakReference<>(new User());

虚引用 PhantomReference

五大原则是哪些

  1. 单一职责 一个接口、类、方法只负责一件事情 

  2. 开闭原则 对修改关闭,对扩展开放

  3. 里氏替换原则 子类可以替换父类, 父类可以接收子类对象, 实现多态(尽量使用父类/接口去new子类)

  4. 依赖倒置 面向接口编程,关注抽象,不关注细节实现

  5. 接口隔离 拒绝胖子接口,接口多个方法隔离到不同的接口中

静态代理和动态代理

  1. 静态代理的缺点是只能针对具体的业务进行代理,无法通用

  2. 动态代理有JDK方式和CGLIB方式

  3. 默认推荐使用JDK方式,该方式要求被代理的类要有接口

  4. CGLIB需要第三方jar包的依赖,可以不要求被代理对象有接口

  5. 代理可以使业务功能增强

JDBC执行流程? 

  1. 加载驱动Class.forName("驱动路径")

  2. 建立连接 DriverManager.getConnection(url,username,password)

  3. 创建普通指令 CreateStatement() 或者预编译指令 PrepareStatement(Sql)

  4. 执行sql语句,调用 executeQueryexecuteUpdate

  5. 最重要的一步,释放与数据库连接的资源. 关闭结果集,关闭指令,关闭连接

    rs.close(), statement.close(), connection.close()

Statement和PreparedStatement的区别?怎么防止SQL注入?

  1. PreparedStatement是Statement的子接口,都为执行SQL指令的接口标准

  2. Statement执行的SQL语句有被SQL注入的风险。

  3. PreparedStatement是预编译,即先编译语句和占位符,执行阶段在加入数据,可以预防SQL注入。

  4. 同时由于PreparedStatement是预编译,Statement是执行层面先编译再执行,所以在多次执行同一SQL的情况下,PreparedStatement具有更高的效率。

----------------------------------------------------数据库分割线-------------------------------------------

什么是SQL ?

  • 结构化查询语言

  • SQL又包含DDL(数据定义语言),DCL(数据控制语言),DQL(数据查询语言),DML(数据操纵语言),TCL(事务控制语言)

  • DDL:负责创建CREATE或修改ALTER或删除DROP数据库对象的,对象有 表,存储过程,函数等等

  • DCL:负责创建或修改或删除数据库用户和角色权限的,控制对象是否有权限访问的

  • DQL:负责查询数据库表和视图的

  • DML:负责添加,删除,修改数据的

  • TCL:负责事务的,如commit,rollback

char、nchar、varchar、nvarchar区别 

  1. char定长,varchar变长,确定大小的使用char效率更高,不确定大小的字段使用varchar

  2. nchar和nvarchar按字符Unicode编码存储,char和varchar按字节存储。

drop,delete,truncate的区别 

  1. drop,truncate属于DDL。 delete属于DML语句。

  2. drop是删除表的结构定义,所以连带数据一起删掉了。delete和truncate只会删除数据,而不会删除定义。

  3. delete可以跟条件删除,truncate不能跟条件。

  4. delete删除速度慢,因为要记录日志。truncate属于截断表,会连带日志和数据一起删除,所以删除速度极快。

数据库三范式 

  1. 第一范式1NF:分割不同的字段到确保不可再分.

  2. 第二范式2NF:确保每一条数据的唯一性。

  3. 第三范式3NF:当前表不要去保存关系表非主关键字以外的其他字段数据。

    3NF避免了数据的冗余性,保证数据的完整性,节省了空间。

    3NF不一定要求必须遵循,数据量体量特别大的地方不要求满足第三范式,以提高查询的效率。

表连接 

  1. 内连接inner join,显示两个表匹配条件的数据,不匹配的不显示

  2. 左外连接left [outer] join,左边主表的数据必定全部显示,被连接的次表如果匹配则显示,不匹配显示为null

  3. 右外连接right [outer] join,右边表的数据必定全部显示,左边表如果匹配则显示,不匹配显示为null

  4. 全连接,两个表匹配的数据会显示,如果不匹配的则各自行的匹配字段显示为null(MySql没有全连接)

  5. 交叉连接cross join,不添加匹配条件,形成笛卡尔积,即A表每条数据和B表每条数据各自匹配一次,如A5条数据B4条数据 结果为20条数据。

  6. 自然连接natural join,无需on条件,两张表中寻找那些数据类型和列名都相同的字段,然后自动地将他们连接起来,并返回匹配结果。

mysql存储引擎有哪些,区别是什么?

  1. mysql主流的存储引擎有innoDB,myisam,memory.

  2. 默认使用的是innoDB.

  3. innoDB和myisam的共同点都支持b+ tree索引。

  4. innoDB和myisam有很多区别,最大的区别有两个

    • innoDB支持事务,而myisam不支持

    • innoDB的数据由frm和ibd存储,数据和索引都在ibd中。myisam的数据由frm,myi,myd三个文件存储,数据存储在myd中,索引存储在myi中。

    • 其他区别:innoDB支持行锁和表锁,myisam只支持表锁

    • innoDB支持外键, myisam不支持外键

    • innoDB支持自动增长auto increment, myisam不支持

    • innoDB查询较低于myisam,修改高优于myisam。

    • Innodb使用的是聚簇索引,MyISam使用的是非聚簇索引

    • PS:聚簇索引是建立在一个表中的主键或唯一键或rowid(只有在没有为表分配主键和唯一键才关联rowid)上,其作用是用户查询辅助索引的时候,可以通过key快速定位到聚簇索引再通过聚簇索引的主键索引找到数据。

union和union all区别 ?

  1. union是将两个表的结果集合并,并且去重,要求列的数量相等。(Oracle会自动排序,且列的类型要兼容)

  2. union all是将两个表的结果集直接合并,不会去重。

谈谈对索引的理解?怎么提升查询效率?有一个表数据量查询很慢,怎么解决?

  1. 索引的作用是大大的提升查询的效率,但是会增加数据修改和录入的时间。

  2. 常用的索引有唯一索引,普通索引,联合索引。其他还有全文索引(不推荐)

  3. 唯一索引必须创建在唯一键或主键上。

  4. innodb下每个表都会有一个聚簇索引,该索引用来提升整行的查询效率。

    聚簇索引默认建立在唯一键或主键上,如果表没有创建唯一键或主键,那么聚簇索引会建立在mysql自带的rowid上。

  5. 可以通过explain分析sql语句,确定索引执行的情况,来优化SQL。

事务是什么

数据库的为了保证数据操作的完整性和一致性,提供了事务的功能。

事务有四个特性来保证数据的安全,分别为ACID

  • 原子性:把整个流程当做一个原子来执行,要么都成功,要么都失败

  • 一致性:事务的执行前,和执行后,数据是一致的

  • 隔离性: 多个事务之间是互相隔离独立的,互不影响的

  • 持久性:事务执行完成后,对数据的操作的永久保存的

MySql中的锁 

  • 行锁 锁住选中的行

  • 表锁 全表

  • 排它锁 for update,添加排它锁,排它锁不允许其他事务在该数据上 再次添加共享锁和排它锁,也不允许修改。

  • 共享锁 lock in share mode,添加共享锁,共享锁允许其他事务在该 数据上再次添加共享锁,但不允许添加排它锁,也不允许修改。

脏读、不可重复读、幻读

  1. 脏读:A事务在修改数据,但是没有提交/回滚,此时B事务查询到了A事务修改的数据,那么这个数据就是脏数据。

    事务隔离级别为read committed时,可以预防该问题。

  2. 不可重复读:A事务在当前事务中前后重复读取多次数据,返回的结果不一致,因为中途有其他B事务修改了该数据,这种情况称为不可重复读。

    事务隔离级别为repeatable read时,可以预防该问题。

  3. 幻读:A事务在当前事务中前后重复读取多次数据,中途有其他事务在表中做了插入或删除数据,导致前后读取的数据【数量】不一致,就像发生了幻觉一样。

    mysql的innoDB引擎事务隔离级别为repeatable read时,可以预防该问题,其他引擎和Oracle需要调整到串行化Serializable级别才能预防该问题。

数据库的隔离级别有哪些?spring有哪些隔级别

  1. Spring有五种,多出来的一种是default,意思是spring不参与设置隔离级别,而是用数据库默认的级别。

  2. Mysql默认使用的是可重复。

  3. Oracle默认使用的是读已提交。

---------------------------------------web编程分割线-----------------------------------------------------

Tomcat目录结构说说 

  1. bin 存储的是启动和停止等可执行文件或脚本

  2. conf 存储的server.xml、context.xml等配置文件,修改端口或连接池信息可以在这里

  3. lib 存储tomcat运行所需jar包的地方,也可以自行为tomcat添加其他jar包放这里

  4. logs 存储tomcat运行的一些日志信息的目录

  5. temp 临时目录,运行生成一些临时文件

  6. webapps 项目执行的地方,把要运行的项目放在这里面

  7. work 工作目录,编译后的jsp文件,会在这里

Servlet的生命周期

  1. 默认在第一次访问的时候,由容器创建Servlet对象,

    并执行init方法。

    如果设置了loadOnStartup为大于等于0的数,那么在容器启动的时候,servlet会按此值升序加载并执行init方法。

    注意:后续不会再次创建Servlet实例,Servlet是单实例的。

  2. 然后每次请求的时候执行service业务方法,HTTPServlet中对service方法已经重写,会根据用户的请求方式分别调用对应的doGet/doPost/doPut/doDelete等方法。

  3. 容器关闭时,会调用destroy方法。

JSP执行原理 

  • java server page Java服务器页面,本质上就是一个Servlet

  • jsp首次执行的时候会将JSP翻译为servlet文件,后续执行不会再次翻译

  • 然后编译并且执行该servlet的service方法

  • 执行完成后,会用response响应输出html的静态代码

JSP包含哪些内容 ?

  1. 指令<%@ %>

  2. 声明<%! %>

  3. 表达式<%= %>

  4. 小脚本<% %>

  5. 注释<%-- --%>

  6. 静态内容HTML

转发和重定向的区别 ?

  1. 转发地址栏不会变。重定向地址栏会改变

  2. 转发是服务器转发,只能转发内部资源,属于一次请求。重定向是二次请求,可以跳转外部链接。

  3. 转发由于地址栏不变,所以刷新会重复提交之前的表单数据。重定向是刷新跳转之后的地址。

GET和POST的区别

  1. get是明文提交,所以对敏感的数据要注意安全性的问题。

  2. post是密文提交,地址栏不可见。

  3. get提交一般用于获取数据。post一般用于修改数据。

  4. get由于是地址栏明文显示,那么地址栏对数据的长度有限制。而post理论上没有限制。

  5. get会被浏览器主动cache,post不会

  6. get只接收ASCII字符,而post没有限制。

JSP的四个作用域 

  1. pageContext 当前页面有效

  2. request 一次请求中有效

  3. session 一次会话中有效

  4. application 一次应用中所有用户有效

JSP的九大内置对象 

  • 所谓内置对象,就是容器自动创建好给我们用的,不用我们创建。

  • out 用于输出内容到客户端

  • page 代表当前页面 类似servlet中的this

  • pageContext 页面上下文

  • config 配置信息对象

  • request 请求对象

  • response 响应对象

  • session 会话对象

  • application 应用对象

  • exception 异常对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值