JAVA知识点总结第三周

目录

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

抽象类    (abstract)

接口       (interface)

  • 封装

封装:就是将显示世界事物的属性隐藏了(加入一个关键字private),    私有的,无法直接访问的,对外数据的安全性!(外界不能访问的)对外提供一个方法,公共的(public)访问方法(setXXX()/getXXX())
   重新创建这个类 来优化上面的代码;加入封装思想

  • private关键字的特点?

  1.  被private修饰的成员变量以及成员方法只能在本类中访问
  2.  可以修饰成员变量也可以成员方法,就是为了外界不能直接访问
  3.  被private修饰的成员变量/成员方法可以间接的通过的方法访问;
  • 局部变量和成员变量的区别?

 1)书写位置不同:

 成员变量:类中,方法外!

局部变量:方法定义中,或者方法声明上

2)内置中的位置不同

成员变量:堆内存中,和对象有关系

  局部变量:栈内存中,和方法有关系

3)生命周期不同:

 成员变量:随着对象的创建而存在, 随着对象的创建完毕等待jvm的垃圾回收器空闲 时候回收而消失

局部变量:随着方法的调用而存在, 随着方法调用结束而消失;

4)初始化值不同:

 成员变量:是可以不初始化的,需要通过对象名来赋值,存在默认初始化;

 局部变量:必须在使用之前初始化,否则报错;

class Demo{

    //成员变量:类中方法外
//    public int num = 20 ;
    public int num  ;

    public void show(String a){ //局部变量
        //局部变量
        //int x = 10 ;
        int x = 5 ; //必须使用之前初始化,否则下面x报错
        System.out.println(a+x);// 报错信息Variable 'x' might not have been initialized
    }
}

//测试类
public class VariableDemo {
    public static void main(String[] args) {

        //要去访问Demo类中num变量
        Demo d = new Demo() ;
        System.out.println(d.num); //对象名.成员变量名;
        d.show("高圆圆");
    }
}
  • this :代表当前类对象的地址值引用

       目的:就是为了区分 局部变量隐藏了成员变量:加入this可以区分
        this.成员变量名 = 局部变量名 ;

  • 匿名对象

  格式:new 类名() ;
  匿名对象调用方法
  new  类名().成员方法名() ;
 好处:节省内存空间,new 类名() ;
匿名对象可以作为参数传递
创建完毕之后,没有栈内存指向,所以使用完毕,立即被GC(垃圾回收器回收)
一般情况:匿名对象使用一次即可,这样不需要过多的去开辟堆内存空间,直接被回收;

class Student{
    public void study(){
        System.out.println("Good Good Study,Day Day Up!");
    }
}
//定义StudentDemo类
class StudentDemo{
    public void method(Student s){//形式参数是一个Student类型,引用类型
        s.study();//调用该方法,应该使用实际参数对象名在访问
    }
}
//测试类
public class NoNameDemo {
    public static void main(String[] args) {
            //要访问StudentDemo类中method方法
        //创建StudentDemo类对象|
        StudentDemo sd = new StudentDemo() ;
        //创建学生对象
        Student s = new Student() ;
        sd.method(s); //方法里面:形式参数 创建学生了学生对象
        System.out.println("---------------------------------");
        //使用匿名对象new  类名()
        //new  类名().成员方法名() ; //调用自己方法
        sd.method(new Student());
        System.out.println("---------------------------------");

        //再次优化:
        //链式编程(自己去玩,开发中很少)
        new StudentDemo().method(new Student());
    }
}


/**
 * 一个类的成员方法:
 *      类的成员变量:描述这个类有哪些属性
 *      类的成员方法:setXXX()/getXXX():赋值和获取值的成员方法以及事物的一些其他行为
 *
 *      类的构造方法
 *          什么是类的构造方法----->是一个方法,比较特殊
 *          1)这个方法,方法名和类名相同
 *          2)这个方法,连void都没有
 *          3)构造方法是可以重载的;
 *                  无参构造方法
 *                  有参构造方法
 *
 *
 *          构造方法的目的:就是为了类的成员相关的数据进行初始化的;
 *                      系统默认初始化
 *                      显示初始化;
 *
 *          注意事项:
 *                  当一个类中没有任何构造方法(无参/有参),系统会默认提供无参构造方法;
 *                  但是当如果提供有参构造方法,系统就不会在提供无参构造方法,无参构造就会报错;
 *
 *                  以后,写一个类的时候,为了防止无参构造无法访问,永远出无参构造方法;
 *
 *
 *           一个标准类的写法:
 *                  成员变量私有化
 *                  提供对外的公共访问方法,setXXX()/getXXX()
 *                  提供无参构造/ 有参构造方法 (根据需求进行判断)
 *
 */
//定义一个学生类
class Student{
    //给没有加入私有的name属性
    String name ;  //默认初始化
    //无参构造方法
    public  Student() {
        System.out.println("这个是Student类的无参构造方法...");
    }
    //有参构造方法
    public Student(String name){//"高圆圆"
        this.name = name ; //局部变量在给成员变量赋值;
        System.out.println("这是Student类的有参构造方法"+name);
    }

}
//测试类
public class ConstructorDemo {
    public static void main(String[] args) {
        //创建Student类对象
        //类名 对象名 = new 类名() ;
        Student s = new Student() ;//无参构造方法---->进行系统默认化
        System.out.println(s);
        System.out.println(s.name);

        System.out.println("-----------------------------------") ;
        //在创建一个新的学生对象
        Student s2 = new Student("高圆圆") ;
        System.out.println(s2);
        System.out.println(s2.name);
    }
}
  • static关键字的特点:

  1. 被静态修饰的随着类的加载而加载,优先于对象存在;
  2. 不能和this共存;
  3.  本身含义就是共享,共用;可以多个对象共享共用;
  • 静态的使用场景适用于范围:(记忆的)

简单记忆:静态只能访问静态; 静态方法中只能访问静态变量静态方法只能调用静态方法;
非静态方法皆可以访问静态的东西也可以访问非静态的东西;

  • ArrayTool: 对ArrayTool.java文件产生一个文档说明书---类似于API(Application Programming Interface:应用程序接口文档)

 使用jdk安装目录里面的bin里面: javadoc.exe 指令  产生文档说书的指令
  1)将ArrayTool这个java文件代码复制到本地某个磁盘上,类名和文件名称一致(先不要把package复制上去)                                                                                                                                             2)打开dos窗口,进入到这个java文件的路径下      (找到这个java文件后,这个类权限保证访问权限足够大:public)
 3)会用javadoc  -d 目录名称 -author -version ArrayTool.java(java源文件带后缀)  产生文档说明书

*ArrayTool类是针对数组操作的工具类,里面包含了数组的遍历功能,求数组最值问题,
 * 获取数组的元素第一次出现索引值,冒泡排序等提供很多功能;

  • 代码块:     使用{}括起来的内容
  •    分类:

   局部代码块,就是在方法定义中使用{}
           {},作用:就是限定局部变量的生命周期;
    构造代码块:---在类的成员位置定义的{},它有特点:在执行构造方法之前,如果类中有构造代码块,
    优先执行构造代码块,作用:也可以给类的成员的数据进行初始化; (实际开发很少见到构造代码块)

        静态代码块:
       类就加载一次,静态代码块也就执行一次!
              格式
                    static{ --->跟静态相关的都和类有关系,随着类的加载而加载;
                    里面书写代码
                    }
                    静态代码块,构造方法,构造代码块
                 优先级:静态代码块 > 构造代码块> 构造方法,而且每次执行构造方法之前,优先执行所有的构造构造代码块


  • 继承

  • 继承: 将多个类的共性内容抽取出来,放在一个独立的类中,让这个独立的类和其他类产生一种关系

 "继承"---关键字 extends

       格式: class 子类名 extends 父类名{}
 

  •    继承的好处:

1)可以提高代码复用性
 2)可以提高代码的维护性,后期便于维护,针对子类和父类进行维护(子父关系明确)
 3)类与类产生的继承关系,是后面讲"多态"的前提条件;
  在Java中有一个开发原则 "低耦合,高内聚"(以后所有的Java设计模式都需要遵循这一个原则)
耦合性:开发中是永远避免不了,可以降低(耦合:类和类的关系)
内聚性:指的是某个类完成某个功能的一种能力; 尽量不要产生继承关系来完成一个功能,一个类能完成一个类完成; 

低耦合:降低耦合性,减少类和类的关系;

  • 继承的特点:

1)在Java语言中,类和的类的关系是一种继承关系,这个继承只能支持"单继承",不支持多继承
2)类和类关系,虽然不支持多继承,但是层层单继承----> 多层继承

如果一个父类存在有参构造方法,没有无参构造方法,子类的所有构造会出现什么问题?出现了问题,怎么解决?
 子类的所有全部构造方法报错,为什么? 子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法
 方案1:
 1)手动给出无参构造方法
 2)假设,人家现在就不需要让你给出父类的无参构造方法;
 就需要让子类的构造方法,显示的访问父类的有参构造方法
----要使用关键字 super:代表父类空间标识(代表的父类对象的地址值引用!)
 super() :访问父类的无参构造方法
 super(xxx) :访问父类的有参构造方法
 这些super一定是在子类构造方法中的第一句话
方案3) 保证子类的所有的构造方法某一个构造方法,让父类初始化完毕即可;
 先通过子类的无参构造方法里面---this(xxx):访问本类(子类)有参构造方法
 在子类的有参构造方法的第一话:让父类初始化 super(xxx):间接访问父类的有参构造方法
子类继承父类,一定要先执行父类的构造方法,初始化完毕之后;然后才能执行子类的构造方法---分层初始化
 

class Fu2{
    /*public Fu2(){
        System.out.println("这是Fu2的无参构造方法...");
    }*/
    public Fu2(String name){
        System.out.println("这是Fu2的有参构造方法...") ;
    }
}
//子类
class Zi2 extends Fu2{
    //给出Zi2的无参构造方法
    public Zi2(){
        //super("随便给") ;

        this("高圆圆") ; //访问本类的有参构造方法
        System.out.println("这是Zi2的无参构造方法...");
        //super("随便给") ; //一定是在第一句话
    }

    public Zi2(String name){
        super("随便给") ;
        System.out.println("这是Zi2的有参构造方法...");
    }
}
//测试类
public class ExtendsDemo4 {
    public static void main(String[] args) {

        //创建子类对象
        Zi2 z = new  Zi2() ; //访问子类的无参构造方法
      /*  System.out.println("------------------------------") ;
        Zi2 z2 = new Zi2("hello") ;*/
    }
}
  • 子类继承父类,成员变量的访问问题;
    情况1: 子类和父类的中成员变量名称不一致,访问比较简单,分别访问即可!
     情况2:子类和父类的成员变量名称一致:  如何访问呢?
    1)先在子类的局部位置找,有没有这个变量,有就使用;
     2)如果没有,在子类成员位置中找,有没有这个变量,有就使用;
     3)如果子类的成员位置也没有,然后会在父类的成员位置找,有没有这个变量,有就使用;
     4)如果父类的成员位置都没有,报错(前提:这个父类没有它的父类了),说明整个子父类中都没有变量;
     遵循"就近原则"
  • 子类继承父类,关于成员方法的访问?

情况1:子类和父类的成员方法名称不一致,比较简单,分别调用即可;
情况2:子类和父类的成员方法一模一样:权限修饰符,返回值类型,参数列表都一样
 子类将父类的方法覆盖了---->方法重写   :Override---->子类在父类的基础上,将父类的覆盖了,使用自己的功能;
 举例: 动物都需要吃
猫类和狗类吃的东西不一样,将Animal类的eat进行重写;

  • 什么是方法重写,什么是方法重载

    方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法
               方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同
方法重载的要求是参数列表不同。具体包括以下三种情形。
①参数的数量不同。
②参数的类型不同。
③参数的顺序不同。

  •     this和super的区别?

    super()是从子类中调用父类的构造方法,this()在同一类调用其他构造方法
               2.super和this均放在构造方法首行
               3.this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

 final:最终的,无法更改的,状态修饰符 ,被final修饰的成员方法,不能被重写,保证父类的方法安全性!

  • final关键字特点:
  1. final可以修饰类,该类不能被继承
  2. final可以修饰变量,此时这个变量是一个"常量",常驻内存;
  3. final修饰成员方法,此时这个方法不能被子类重写,目的为了保证方法中某些数据的 安全性!

  • 多态

多态:宏观角度:一个事物在不同时刻体现的不同形态
           微观角度:具体对象在内存 中的变化

  •        多态的前提条件

1)必须有继承关系(类与类),没有继承关系,不谈多态

2)必须存在方法重写,子类部分功能要将父类的功能进行覆盖,重写,子类使用自己的功能体现
3)必须存在父类引用指向子类对象:

  • 多态的成员访问特点:

父类名  对象名  = new  子类名();
1)成员变量:编译看左,运行看左;
2)成员方法:非静态 编译看左,运行看右,因为子类重写了父类的功能
    静态方法:即使子类出现了和父类一模一样静态方法,不算重写,因为静态方法都算自己类相关的,类成员  编译看左,运行看左
3)构造方法:多态的前提条件,有继承关系,跟继承一样,分层初始化,先执行父类的构造方法,然后再是子类的构造方法

  • 多态的弊端:

 1)有继承关系了 2)有重写了 3)有父类引用指向子类对象 Fu f = new Zi() ; 无法调用子类的特有功能! 如何解决呢?
方案1:创建自己的子类对象
子类名 对象名 = new 子类名() ;
方案1不好地方:本身Fu fu = new Zi() ;已经开辟堆内存空间了,
Zi zi = new Zi();又要在堆内存开辟空间,消耗内存空间比较大 ;
方案2: 多态的第三个前提条件:父类引用指向子类对象
能不能将 将父类的引用 强制为子类的引用呢?
 可以向下转型
前提必须向上转型Fu fu = new Zi() ;
Zi z  = (Zi)fu ;  //强转的语法    这样的好处:节省内存空间

  • 多态的好处:

 1)提高代码的复用性,由继承保证的
 2)提高代码的扩展性,由多态保证 : 父类引用指向子类对象

  • instaceof :关键字:

        格式:一般是用于判断场景用的:
        if(变量名  instanceof  引用数据类型(多态)){}  判断前面这个变量名是否为指定的数据类型(堆内存中的变化)  true:表示是指定的类型;false:不是指定的类型


  • 抽象类

  • 什么是抽象类?
      在一个类中,如果有抽象方法,这个类必须为抽象类
  • 抽象类的特点:
    1)不能实例化 (不能创建对象)
    2)必须强制子类完成事情:必须将抽象方法重写!
     抽象类的子类:
     如果子类是一个抽象类,  没有意义(抽象类new不了) (前提条件是这个子类没有它的子类)
    研究的抽象类的子类一定会有一个具体类,这个时候通过具体类才能创建对象;
     抽象的父类名  对象名  = new 具体的子类名() ;  抽象类多态
  • abstract  class Animal{ //必须为抽象类
        //仅仅给出一个吃的声明,没有方法体的方法 ---->抽象方法  abstract
        public abstract  void eat();  //没有方法体,必须要子类将方法进行"实现"
    
        //抽象方法
        public abstract  void sleep() ;
    
        //非抽象方法
        public void show(){
            System.out.println("show Animal");
        }
    
    }
    
    //猫类
    //abstract  class Cat extends  Animal{ //没有意义
      class Cat extends  Animal{ //具体类
        @Override
        public void eat() {//只要见到具体的事物,才知道吃啥
            System.out.println("猫吃鱼");
        }
    
        //重写抽象类的sleep方法
        @Override
        public void sleep() {
            System.out.println("猫躺着睡");
        }
    
    }
    //狗类
    class Dog extends  Animal{
        @Override
        public void eat() {
            System.out.println("狗吃骨头");
        }
        @Override
        public void sleep() {
            System.out.println("狗趴着睡");
        }
    }
    
    //测试类
    public class AbstractDemo {
    
        public static void main(String[] args) {
            //创建父类对象
            //Animal a = new Animal() ;//抽象类不能实例化(不能new)
    
            //  抽象的父类名  对象名  = new 具体的子类名() ;  抽象类多态
            //Animal a  = new Cat() ; //抽象类的子类是一个抽象类
            Animal a  = new Cat() ; //抽象类的子类是一个具体类   抽象类多态
            a.eat(); //多态的成员方法:编译看左,运行看右!
            a.sleep();
            a.show();
        }
    }

  • 抽象类的成员特点:
     成员变量:抽象类的成员变量既可以有变量,也可以是自定义常量被final
     成员方法:抽象类中既可以有抽象方法,也可也有非抽象方法
     构造方法:既可以定义无参/有参构造方法...
     存在抽象类多态,有继承关系,初始化的时候,构造方法----分层初始化---->先父类初始化,子类初始化
  • abstract  class Person{ //抽象类
    
        //定义一个成员变量
        public int num = 100 ;   //变量
    
        public final int num2 = 200 ;  //自定义常量  num2不能在改变
    
        //人都要学习---具体的人才具备具体的动作行为----方法抽象化
        public abstract  void study();
    
        //无参构造方法
        public Person(){
            System.out.println("这是Person类的无参构造方法");
        }
    
        public void method(){//非抽象方法
            System.out.println(num) ;
            System.out.println(num2);
        }
    }
    //学生类
    class Student extends  Person{
    
        //无参构造方法
        public Student(){
            System.out.println("这是Student的无参构造方法");
        }
    
        @Override
        public void study() {
            System.out.println("学生主要目的学习专业知识");
        }
    }
    
    //测试类
    public class AbstractDemo2 {
        public static void main(String[] args) {
    
            //抽象类多态测试
            Person p = new Student() ;
            p.method();
    
            p.study() ;
        }
    }
    

  • abstract 和那些关键字冲突
     和private关键字冲突:因为被private私有的成员方法只能在本类访问,而abstract修饰的成员方法           必须强制子类重写,已经超出来的当前类的范围
    和final也冲突,被final修的成员方法,不能被重写;而抽象方法强制子类必须重写;
    和static也冲突,abstract修饰的方法必须被子类重写,而static修饰的方法,算不上抽象,直接跟类相关的;
    abstract关键字 应用范围: 定义在类上---抽象类
    定义在方法上----抽象方法
    public abstract  返回值类型 方法名(空参/带参...)  ;
     abstract 返回值类型 方法/名(空参带参...)  ;
  • 子类继承父类,子类重写父类的抽象方法,必须保证访问权限足够大,要么加public要么跟父类的方法保持一致!否则报错;

  • 接口

  • 接口:体现这些事物本身不具备的功能,要经过一些特殊的实现才能具备功能-----称为 "接口"---关键字 interface


 格式的写法
    interface  接口名{   //命名规范和类名命名一样,见名知意 "大驼峰命名法"
                  只能为抽象方法
           }

接口的子类----"子实现类"
  实现
 class 子类名  implements  接口名{
 }
 接口比抽象类还抽象---->特点:不能实例化

interface Jump{
    /*public void jump(){  //接口中的只能是抽象方法

    }*/
    public abstract void jump() ;//因为 它默认修饰符 public abstract:可以省略不写
}
//跳高猫
 class Cat  implements  Jump{

    @Override
    public void jump() {
        System.out.println("猫可以跳高了");
    }
}

//测试类
public class InterfaceDemo {
    public static void main(String[] args) {

        //Jump jump2  = new Jump() ;//接口不能实例化,需要通过子实现类实例化(必须为具体类)
        //测试:接口多态---接口名 对象名 = new 子实现类名();
        Jump jump = new Cat() ;
        jump.jump();
    }
}

接口---体现事物本身以外的额外功能,需要事物要对接口的功能要进行实现,才具备!

  •  接口的定义

 interface 接口名{}   接口和类名的命名规范同理,遵循"大驼峰命名法"
接口的最大特点: 不能实例化
 如何实例化?
 *接口通过它的子实现类进行实例化(前提,这个类实现 implements 接口)
 class 子实现类名 implements 接口名{
  }
 实际开发中:接口的子实现类名的命名---> 接口名的后面+Impl:表示是接口的实现类

  •  接口的成员特点:

 1)成员变量:只能是常量,存在默认修饰符 :public static final
2)成员方法:只能是抽象方法,存在默认修饰符  public abstract
 3)构造方法:没有构造方法的---通过子实现类的构造方法来实例化
接口本身意义:对外暴露这些功能,让子实现类实现 !
 

//定义接口
interface Inter{
//    int num = 20 ; //隐藏了默认修饰符public static final 可以省略不写的
    public static final int num = 20 ;

    /*void show(){
        System.out.println("show Inter");
    }*/
    //void show() ; //省略了默认修饰符 public abstract ,可以省略不写
    public abstract  void show() ;

   /* public Inter(){ //不能这样写

    }*/
}
//提供具体的子实现类
                  //实现
class InterImpl implements  Inter{//实现类必须实现接口的抽象方法,否则报错
    @Override
    public void show() {
        System.out.println("show InterImpl");
    }

}

//测试类
public class InterfaceDemo {
    public static void main(String[] args) {
        //创建Inter对象
        //Inter inter = new Inter() ; //接口不能实例化:  Inter is abstract
        //所以,通过接口指向子实现类名
        //接口名 对象名 = new 子实现类名() ;  //接口多态
        Inter inter = new InterImpl() ;
        System.out.println(inter.num); //编译看左,运行看左
        //inter.num = 30 ;  //报错:final修饰的变量:最终的.无法更改的, 不能在被赋值
        System.out.println(Inter.num) ;  //接口比抽象类还抽象  之前:类名.变量名; 变量被static修饰
                                        //接口名.变量名 ; 变量被static修饰
    }
}


 关于面向对象中牵扯关系问题:    Java中最基本的单元是类
类和类:继承关系 extends,Java语言中只支持单继承,不支持多继承,但是可以多层继承
类和接口: 实现关系 implements;一个类继承另一个类的同时,可以实现多个接口
接口和接口:继承关系:extends   不仅支持单继承,也可以多继承!

 

package com.qf.interface_01;


/*class GrandFu{}
class Fu extends GrandFu{}
class Zi extends Fu{}*/

//父接口
interface Love{
    void love() ;
}
//父接口
interface StudyEnglish{
    void speakEnglish() ;
}

//定义一个接口
interface Inter2 extends Love,StudyEnglish{ //接口与接口---> 继承关系  :单继承 / 可以多继承
    void show() ;
}
interface  Inter3{
    void function() ;
}
//父类 ---抽象类
abstract  class   SuperIner{
    public abstract  void method();
}
//子实现类
class InterImpl2 extends SuperIner  implements  Inter2,Inter3{//一个类继承另一个类的同时,可以实现多个接口

    //来自Inter2接口的方法
    @Override
    public void show() {
        System.out.println("show InterImpl2");
    }

    //来自Inter3接口
    @Override
    public void function() {
        System.out.println("function InterImpl2");
    }


    //来自抽象的父类
    @Override
    public void method() {
        System.out.println("method InterImpl2");
    }

    //来自与Inteer2接口继承的另一个接口Love的接口的方法
    @Override
    public void love() {
        System.out.println("爱生活,爱高圆圆...");
    }

    @Override
    public void speakEnglish() {
        System.out.println("会说英语");
    }
}

//测试类
public class InterfaceDemo2 {
    public static void main(String[] args) {
        //谁的功能最多: 最具体的类 InterImpl2
        //具体类  对象的创建
        InterImpl2 interImpl2 = new InterImpl2() ;
        interImpl2.function();
        interImpl2.show();
        interImpl2.love();
        interImpl2.speakEnglish();
        interImpl2.method(); //继承的它的抽象类的方法
    }
}
  • 抽象类和接口的区别?

抽象类:
构造方法:有构造方法,用于子类实例化使用(自己不能实例化)
成员变量:可以是变量,也可以是常量
成员方法:可以是抽象的,也就可以是非抽象的
接口:
构造方法:没有构造方法 不能实例化
成员变量:只能是常量
成员方法:只能是抽象的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值