Java基础面试题

Java基础面试题(2020)

1、java的安全性

语言层次的安全性:

Java取消了强大又危险的指针,而代之以引用,由于指针可以进行移动,可以随便指向一个内存区域,不管这个区域是否可用,这样做是危险的,因为原来这个内存地址可以能存储着比较重要的数据,而且使用指针也容易数组越界。

垃圾回收机制:

不需要程序员直接控制内存回收,由垃圾回收器在后台自动回收不再使用的内存,避免我们忘记回收而导致内存泄漏。避免程序错误回收程序核心类库的内存,导致系统崩溃。

异常处理机制:

Java异常机制主要依赖于try、catch、finally、throw、throws五个关键字。

强制类型转换:

只有在满足强制转换规则的情况下才能强转成功。

底层安全性:

Java在字节码的传输过程中使用了公开密钥加密机制(PKC)

在运行环境提供了四级安全性保障机制:

字节码校验器–类装载器–运行时内存布局–文件访问限制

2、Java三大版本

Java2平台包括标准版(J2SE)、企业版(J2EE)、和微缩版(J2ME)三个版本:

J2EE:Java核心类语言:数据连接、接口定义、输入/输出、网络编程

J2SE:包含J2EE中的类,并且还包含用于开发企业级应用的类:servlet、JSP、XML、事务控制

J2ME:包含J2SE中的类,用于消费类电子产品的软件开发:呼机、智能卡、手机、机顶盒

3、什么是JVM?什么是JDK?什么是JRE?

JVM:

JVM是java虚拟机的缩写,它是整个java跨平台的最核心部分,所有java程序会首先被编译为.class文件,这种类可以直接在虚拟机上执行,也就是说class并不直接与机器的操作系统相对应,而是经过虚拟机间接与操作系统交互。JVM的主要工作是解释自己的指令集到CPU的指令集或对用的系统调用,保护用户免被恶意程序骚扰。JVM对上层的Java源文件是不关心的,他关注的只是由源文件生成的类文件。

JRE:

Java运行环境,只有jvm还不能让class文件执行,因为在解释class的时候,JVM需要调用所需的类库lib。jvm和lib合起来就成为jre。JRE的地位就像一台PC机,我们写好的Win32应用程序需要操作系统帮我们运行,同样的,我们编写的java程序也碧血要jre才能运行。

JDK:

java开发包,在安装目录下有6个文件夹,一个src类库源码压缩包和几个声明文件。其中,真正在运行java时起作用的是一下四个文件夹:bin、include、lib、jre。关系:JDK包含JRE,而JRE包含JVM

  • bin:最主要的是编译器(javac.exe)
  • include:java和jvm交互用的头文件
  • lib:类库
  • jre:java运行环境

总的来说,JDK适用于java程序的开发,而JRE则是只能运行class而没有编译功能。

JDK、JRE、JVM三者关系如下:

JDK是java程序开发时用的开发工具包,内部也有JRE运行环境JRE。JRE是java程序运行时需要的运行环境,就是说,如果你不是搞开发的,只是去运行Java程序的话,只安装JRE就可以了。JDK、JRE内存都包含java虚拟机JVM,java虚拟机内存包含许多应用程序的类的解释器和类加载器等等。

4、八大基本数据类型

关键字字节数
整数型byte1
short2
int4
long8
浮点型float4
double8
布尔型boolean1(位)
字符型char2

5、i++和++i的异同之处

相同点

  • i++和++i都是变量自增1,都等价于i=i+1
  • 如果i++,++i是一条单独的语句,两者没有任何区别
  • i++和++i的使用仅仅针对变量,5++和++5会报错,因为5不是变量

不同点

如果i++和++i不是一条单独的语句,他们就有区别

i++:先运算,后增1

int x = 1;
int y = x++;
System.out.println(x+","+y);  //结果:x=6,y=5

++i:先增1,后运算

int x = 1;
int y = ++x;
System.out.println(x+","+y);  //结果:x=6,y=6

6、&和&&,|和||的区别和联系

&和&&的联系(共同点):

&和&&都可以用作逻辑与运算符,但是要看使用时的具体条件来决定。

操作数1&操作数2,操作数1&&操作数2

表达式1&表达式2,表达式1&&表达式2

**情况1:**当上述的操作数都是boolean类型变量时,&和&&都可以用作逻辑与运算符。

**情况2:**当上述的表达式结果是boolean类型变量时,&和&&都可以作为逻辑与运算符。表示逻辑与(and),当运算符两边的表达式的结果或操作数都为true时,整个运算结果才为true,否则,只要一方为false,结果都为false。

&和&&的区别(不同点):

1.&称为逻辑与运算符,&&称为短路与运算符,也可以叫逻辑与运算符。

对于&:无论任何清空,&两边的操作数或表达式都会参与计算。

对于&&:当&&左边的操作数位false或左边表达式结果都为false时,&&右边的操作数或表达式将不参与计算,此时最终结果都为false。

综上所述:如果逻辑与运算的第一个操作数时false或第一个表达式的结果都为false时,对于第二个操作数或表达式是否进行计算,对最终结果都没有影响,结果肯定时false。推荐平时多使用&&,因为它效率更高些。

2.&还可以作为运算符。当&两边操作数或两边的表达式的结果不是boolean类型时,&用于按位与运算符的操作。

|和||的区别和联系与&和&&的区别和联系类似。

7、用最有效率的方法算出2乘以8等于多少

使用位运算,位运算符时对操作数以二进制比特位为单位进行操作计算的,操作数和结果都是整型数。

对于位运算符"<<",是将一个数左移n位,就相当于乘以了2的n次方,那么,一个数乘以8只要将其左移3位即可,位运算cpu直接支持的,效率最高。所以,2乘以8等于几的最效率的方法是2<<3

8、基本数据类型的类型转换规则

基本数据类型分为自动转换和强制转换

自动转换:

容量小的数据类型可以自动转换成容量大的数据类型,也就是说低级别自动向高级别转换。这的容量指的不是字节数,而是指类型表述的范围。

强制转换:

高级别转为低级别 需要强制转换。

如何转换?

赋值运算符“=”两侧的转换,若左边级别>右边级别,会自动转换;若左边级别 == 右边级别,不用转换;若左 边级别 < 右边级别,需强制转换。

9、if和switch的异同之处

相同之处:

都是分支语句,多超过一种的情况进行判断处理

不同之处:

switch更适合多分支情况,判断条件单一,只有一个入口,在分支执行完之后,如果没有break跳出,不加判断的执行下去;而if–elseif—else多分支主要适用于分支比较少的结构,判断类型不是单一,只要一个分支被执行后,后边的分支不再执行。

switch为等值判断,不允许加>=,<=,而if为等值和区间都可以,if的使用范围更大。

10、while和do-while循环的区别

while先判断后执行,第一次如果为false,循环体一次都不执行

do-while先执行后判断,最少执行一次

如果while循环第一次判断为true,则两种没有区别

11、break和continue的作用

**break:**结束当前循环并跳出循环体

**continue:**结束本次循环,循环体中后续的语句不执行,但是循环没有结束。

12、数组的特征

数组是(相同类型数据)的(有序)(集合)

数组会在内存中开辟一块连续的空间,每个空间相当于之前的一个变量,称为数组的元素

元素的表示 数组名[索引]

索引从0开始

每个数组元素都有默认值double 0.0;boolean false;int 0

数组元素有序的,不是大小顺序,而是索引的顺序

数组中可以存储基本数据类型,可以存储引用数据类型;但是对一个数组而言,数组的类型是固定的,只能是一个length:数据的长度

数组的长度是固定的,一经定义,不能再发生变化(数组的扩容)

13、冒泡排序

冒泡排序是一种计算机科学领域的比较简单的排序算法。

它重复走访要排序的列,以此比较两个相邻的元素,如果他们的顺序错误,就把他们交换过来,直到没有相邻的元素需要交换。

冒泡排序原理:

1.比较相邻的元素,如果第一个比第二行个大,就交换他们两个。

2.对每一对相邻元素做同样的工作,从开始第一对到最后一对,再这一点,最后的元素应该回事最大的数。

3.针对所有元素重复以上步骤

4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

public class Bubble {
    private int[] sort(int[] array){
        int temp = 0;
        //外层循环,它决定一共走几趟   -1 为了防止溢出
        for (int i = 0; i < array.length-1; i++) {
            int flag = 0;  //通过符号位可以减少无谓的比较,如果已经有序了,就退出循环
            //内层循环,它决定每趟走一次
            for (int j = 0; j < array.length-i-1; j++) {
                //如果后一个大于前一个 则换位
                if (array[j+1]>array[j]){
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                    flag = 1;
                }
            }
            if (flag == 0){
                break;
            }
        }
        return array;
    }
    //测试
    public static void main(String[] args) {
        Bubble bubble = new Bubble();
        int[] array = {1,3,23,4,43,7,9,65,45};
        int[] sort = bubble.sort(array);
        for (int i : sort) {
            System.out.println(i+"\t");
        }
    }

14、选择排序

选择排序是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小的或最大的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最大最小元素,然后放到已排序列的末尾。以此类推。直到排列完毕,算则排序是不稳定的排序方法。

public class SelectSort {
    private int[] sort(int arr[]){
        int temp = 0;
        for (int i = 0; i < arr.length-1; i++) {
            // 认为目前的数就是小的, 记录小数的下标
            int minIndex = i;
            for (int j = i; j < arr.length; j++) {
                if (arr[minIndex] > arr[j]){
                    // 修改小值的下标
                    minIndex = j;
                }
            }
            // 当退出for就找到这次的小值,就需要交换位置了
            if (i != minIndex) {
                //交换当前值和找到的小值的位置
                temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
        return arr;
    }
    //测试
    public static void main(String[] args) {
        SelectSort selectSort = new SelectSort();
        int[] array = {1,3,6,8,23,56,43};
        int[] sort = selectSort.sort(array);
        for (int i : sort) {
            System.out.println(i);
        }
    }
}

15、插入排序

有一个已经有序的数据序列,要求再这个已经排好的数据序列中插入一个数,但要求插入后数据序列仍然有序,这个时候就要用到一种新的排序方法—插入排序法

插入排序的基本操作就是将一个数据插入到已经排好序的数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量的数据排序,是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就指包含这一个元素(即将插入元素)。再第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。

插入排序思想:每步将一个待排序的记录,按其关键码的大小插入前面已经排序的文件中适当位置上,直到全部插入完毕为止。

public class InsertSort {
    private int[] sort(int[] arr){
        //如果传入的数组为空或者只有一个值,就直接返回
        if (arr == null || arr.length < 2){
            return arr;
        }
        //不为空则进循环判断        
        //外层循环控制总数量
        for (int i = 1; i < arr.length; i++) {
            //内层循环依次减少并提出结果 
            for (int j = 1; j > 0; j--) {
                //如果当前数字小于前一个,则交换,否则不变
                if (arr[j]<arr[j-1]){
                    int temp = arr[j];
                    arr[j] = arr[j-1];
                    arr[j-1]=temp;
                }else {
                    break;
                }
            }
        }
        return arr;
    }
    //测试
    public static void main(String[] args) {
        InsertSort insertSort = new InsertSort();
        int[] array = {2,5,4,7,65,23,45,56,98};
        int[] sort = insertSort.sort(array);
        for (int i : sort) {
            System.out.println(i);
        }
    }
}

16、类和对象的关系

类是对象的抽象,而对象是类的具体实例。类是抽象的,不占内存的,而对象是具体的,占用储存空间。类是用于创建对象的蓝图,类就是一个带方法和变量的特定类型。

类和对象好比图纸和实物的关系,模件是铸件的关系。

比如人类就是一个概念,人类具有身高,体重等属性,人类可以做吃饭,说话等方法。

17、面向过程和面向对象的区别

两者都是软件开发思想,现有面向过程,后有面向对象。在大型项目中,针对面向过程的不足退出了面向对象开发思想。

区别

面向过程:事物比较简单,可以用线性的思维去解决

面向对象:事物比较复杂,使用简单的线性思维无法解决

共同点

面向过程和面向对象都是解决实际问题的一种思维方式

二者相辅相成,并不是对立的。

解决复杂问题,通过面向对象方式便于我们从宏观上把握事务之间的复杂关系、方便我们分析整个系统,具体到微观操作,仍然使用面向过程的方式来处理。

比喻:

面向过程是蛋炒饭,面向对象是盖浇饭。盖浇饭的好处就是“菜”,“饭”分离,从而提高了制作盖浇饭的灵活性,饭不满意就换饭,菜不满意就换菜。用软件工程的术语就是可维护性比较好,耦合度低

区别:

**编程思路不同:**面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类、属性及其方法,然后通过实例化类、执行方法来完成功能。

**封装性:**都具有封装性,但是面向过程是封装的功能,而面向对象封装的是数据和功能。

面向对象具有继承和多态性,而面向过程没有继承性和多态性,所以面向对象优势是明显。

方法重载和方法重写的区别:
英文位置不同作用不同
重载overload同一个类中在一个类里面为一种行为体哦那个多种实现方式并提高可读性
重写override子类和父类间父类方法无法满足子类的要求,子类通过方法重写满足要求
修饰符返回值方法名参数抛出异常
重载无关无关相同不同无关
重写大于等于小于等于相同相同小于等于

18、this和super关键字的作用

this可以调用成员变量,不能调用局部变量;this也可以调用成员方法,但是在普通方法中可以省略this,在构造方法中不允许省略,必须是构造方法的第一条语句,在静态方法中不允许出现this关键字。

super可以直接调用父类的成员变量、成员方法、构造方法,只限构造方法中使用,且必须是第一条语句。

19、static关键字的作用

static可以修饰变量、方法、代码块和内部类

static属性属于这个类所有, 当用static关键字修饰全局变量时,该变量的作用域仅限于当前文件,工程中的其他文件不可以访问到该全局变量。

存放位置:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eToY4cQP-1589162877845)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1589115215197.png)]

访问方式:

**静态变量:**类名.变量名Studnet.schoolName=“清华大学”;

内存中分配空间的时间:

static内部类:属于整个外部类,而不是属于外部类的某个对象。不呢个访问外部类的非静态成员方法,可以访问外部类的静态成员。

20、final和abstract关键字的作用

final和abstract是功能相反的两个关键字,可以对比记忆。

abstract可以用来修饰类和方法,不能用来修饰属性和构造方法;使用abstract修饰的类是抽象类,需要被继承,使用abstract修饰的方法是抽象方法,需要被子类重写。

final可以用来修饰类、方法和属性,不能修饰构造方法。使用final修饰的类不能被继承,使用final修饰的方法不呢个被重写,使用final修饰的变量的值不能被修改,所以就成了常量。

21、final、finally、finalize的区别

final:修饰符 如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承,例如:String类,Math类等。将变量或方法声明为final,可以保证他们在使用中不被改变。被声明为final的变量必须再声明时给定初始值,而在以后的以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重写,但是能够重载。使用final修饰的对象,对象的引用地址不能变,但是对象的值可以变。

**finally:**在异常处理时提供finally块来执行任何清楚操作。如果有finally的话,则不管是否发生异常,finally语句都会被执行。一般情况下,都把关闭物理连接(IO流、数据库连接)等相关操作,放入到此代码块中。

**finalize:**方法名。java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要清理工作。finalize()方法实在垃圾收集器删除对象之前被调用的。他是在OBject类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。一般情况下,此方法由jvm调用,程序员不要去执行调用!!!

22、写出java.lang.Object类中的六个常用方法

  • equals()–比较对象的地址值是否相等
  • hashCode()–获取哈希码
  • toString()–把数据转变成字符串
  • getClass()–获取类结构信息
  • finalize()–垃圾回收前执行的方法
  • clone()–克隆
  • wait()–多线程中等待功能
  • notify()–多线程中唤醒功能
  • notyfyAll()–多线程中唤醒所有等待线程的功能

23、权限修饰符的区别

类的访问权限只有两种:

Public公共的 可被同一项目中所有的类访问。

default默认的,可以被同一个包中的类访问。

成员变量方法的访问权限共有四种:

public 公共的 可以被项目中所有的类访问

protected 受保护的 可以被这个类本身访问;同一个包中的所有其他的类访问;被它的子类访问。

default 默认的被这个类本身访问;被同一个包中的类访问。

private 私有的 只能被这个类本身访问

24、继承条件下构造方法的执行过程

情况1

如果子类的构造方法中没有通过super显示条用父类的有参构造方法,也没有通过this显示调用自身的其他构造方法,则系统会默认先调用父类的无参构造方法,在这种情况下,写不写super()语句,效果是一样的。

情况2

如果子类的构造方法中通过super显示调用父类的有参构造方法,那将执行父类相应构造方法,而不执行父类无参构造方法。

情况3

如果子类的构造方法中通过this显示调用自身的其他构造方法,在相应狗仔方法中应用以上两条规则。

特别注意的是,如果存在多继承关系,在创建一个子类对象时,以上规则会多次向更高一级父类应用,一直执行到顶级父类Object类的无参构造方法为止。

25、==和equals的区别和联系

“==”是关系运算符,equals()是方法,同时他们的结果都返回布尔值;

“==”的使用情况如下

  • 基本类型,比较的是值
  • 引用类型,比较的是地址
  • 不能比较没有父子关系的两个对象

equals()方法使用如下:

  • 系统类一般已经覆盖了equals(),比较的是内容
  • 用户自定义类如果没有覆盖equals(),将调用父类的equals(比如是Object),而Object的equals比较的是地址
  • 用户自定义类需要覆盖父类的equals()

**注意:**Object的==和equals比较的都是地址,作用相同

26、谈谈java的多态

多态是同一个行为具有多个不同表现形式或形态的能力。

多态就是同一个接口,使用不同的实例而执行不同操作。

#现实中,比如我们按下 F1 键这个动作:

#如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;
#如果当前在 Word 下弹出的就是 Word 帮助;
#在 Windows 下弹出的就是 Windows 帮助和支持。
同一个事件发生在不同的对象上会产生不同的结果。

优点:

  1. 消除类型之间的耦合度
  2. 可替换性
  3. 可扩充性
  4. 接口性
  5. 灵活性
  6. 简化性

实现多态的三个条件(前提条件,向上转型,向下转型)

  1. 继承的存在(继承是多态的基础,没有继承就没有多态)
  2. 子类重写父类的方法(多态下会调用子类重写后的方法)
  3. 父类引用变量指向子类对象(涉及子类到父类的类型转换)

27、简述java的垃圾回收机制

传统的C/C++语言,需要程序员负责回收已经分配的内存。

显示回收垃圾回收的缺点:

  1. 程序员忘记及时回收,从而导致内存泄漏,降低系统性能。
  2. 程序错误回收程序核心类库的内存,导致程序崩溃

Java语言不需要陈煦园直接控制内存回收,是由JRE在后台自动回收不再使用的内存,称为垃圾回收机制,简称GC;

  1. 可以提高编程效率
  2. 保护程序的完整性
  3. 其开销影响性能。Java虚拟机必须跟踪程序中有用的对象,确定哪些是无用的。

垃圾回收的特点:

  1. 垃圾回收机制回收JVM堆内存里对象空间,不负责回收栈内存数据

  2. 对其他物理来凝结,比如数据库、输入输出流、Scpket连接无能为力

  3. 垃圾回收机制具有不可预知性,程序无法精准控制垃圾回收机制执行

  4. 可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收改对象

    现在的JVM有多种垃圾回收机制的算法,表现各异。

垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用改对象,则会重新激活对象)

程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否会进行垃圾回收依然不确定。

永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。


28、基本数据类型和包装类

1.八个基本数据类型的包装类

基本数据类型包装类
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble
booleanBoolean
charCharacter

为什么要为基本类型引用包装类

  1. 基本数据类型有方便之处,简单,高效。
  2. 但是Java中的基本数据类型却不是面向对象的(没有属性和方法),这在实际使用时存在很多的不便(比如集合的元素只能是Object),为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行包装,这样八个和基本数据类型对应的类统称为包装类

包装类和基本类型之间的转换:

  • 1包装类— wrapperInstance.xxxValue() ------>基本数据类型
  • 2包装类<—new WrapperClass(primitive)-- new WrapperClass(string)------基本数据类型

自动装箱和自动拆箱

JDK1.5提供了自动装箱和自动拆箱功能,从而实现了包装类和基本数据类型之间的自动转换。

包装类还可以实现基本类型变量和字符串之间的转换

基本类型变量------------String.valueof()------------>字符串 基本类型变量<------------WrapperClass.parseXxx(string)------------字符串

29、Integer和Int的区别

int是java提供的八种原始数据类型之一,java为每个原始类型提供了封装类,Integer是java为int提供的封装类。

int的默认值为0,Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,假如,想要表达出没有参加考试和考试成绩为0的区别,只能使用Integer。

另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。

30、java.sql.Date和java.util.Date的联系和区别

  1. java.sql.Date 是 java.util.Date 的子类
  2. java.util.Date 是 JDK 中的日期类,精确到时、分、秒、毫秒
  3. java.sql.Date 与数据库 Date 相对应的一个类型,只有日期部分,时分秒都会设置为 0,如:2019-10-23 00:00:00
  4. 要从数据库时间字段取 时、分、秒、毫秒数据,可以使用 java.sql.Timestamp

)------------字符串

29、Integer和Int的区别

int是java提供的八种原始数据类型之一,java为每个原始类型提供了封装类,Integer是java为int提供的封装类。

int的默认值为0,Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,假如,想要表达出没有参加考试和考试成绩为0的区别,只能使用Integer。

另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量。

30、java.sql.Date和java.util.Date的联系和区别

  1. java.sql.Date 是 java.util.Date 的子类
  2. java.util.Date 是 JDK 中的日期类,精确到时、分、秒、毫秒
  3. java.sql.Date 与数据库 Date 相对应的一个类型,只有日期部分,时分秒都会设置为 0,如:2019-10-23 00:00:00
  4. 要从数据库时间字段取 时、分、秒、毫秒数据,可以使用 java.sql.Timestamp
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值