Java面向对象(day03)

 

目录

面向对象

对象的创建与使用

封装性:

构造方法:

this关键字

static关键字

继承

方法的覆盖

关于Java语言中的多态语法机制

final关键字

关于JAVA语言当中的包机制:

访问控制权限

super关键字

抽象类

从键盘输入

接口

完整代码:


面向对象

    /*
    面向对象的三大特征:
    封装
    继承
    多态
    采用面向对象的方式开发一个软件:(专业术语要记住)
    面向对象的分析:OOA
    面向对象的设计:OOD
    面向对象的编程:OOP
    类和对象的概念:
    类:在现实世界中不存在,是一个模版,是一个概念,是人大脑抽象出来的东西,
    代表了一类事物,在现实世界中,对象A和对象B拥有共同的特征,进行抽象总结出的一个模板,这个模板称为类
    对象:是实际存在的个体,现实世界中实际存在
    软件开发的整个过程:
    观察现实世界,找出对象
    寻找了N个对象后,找出其共同特征
    程序员在大脑中形成一个模板(类)
    java代码来表述这个类
    java程序中有了类的定义
    通过类创建对象
    有了对象之后,让所有对象协作起来,产生一个完整的系统

    1.类的定义:
    语法结构:
    [修饰符列表] class 类名{、

    }
    数据类型:
    基本数据类型:
    byte
    short
    int
    long
    ....
    引用数据类型:
    String
    student
    System
    user
    customer
    Product
    .......
    能够定义:
    String address=....
    student s=......

  对象的创建与使用

    属性:变量定义在类体之中,方法体之外,这种变量称为成员变量
    通过一个类可以实例化N个对象
    实例化对象的语法:new 类名();
    new是java语言中的一种运算符
    作用为:创建对象,在JVM的堆内存当中开辟新的内存空间
    方法区内存空间:在类加载的时候,class字节码代码片段被加载到该内存空间中
    栈内存空间(局部变量):方法代码片段执行的时候,会给该方法分配内存空间,在栈内存中压栈
    堆内存:new的对象在堆内存中存储
    Student s=new Student();
    Student是一个引用数据类型,s是一个变量名(称为引用),new Student()是一个学生对象
    s作为局部变量,在栈内存中存储,它存放的是new Student()在堆内存中存放的地址
    对象:new运算符在堆内存中开辟的新的空间
    引用:引用是一个变量,只不过这个变量保存着另一个对象的内存地址
    在Java语句中程序员只能通过引用去访问堆内存中对象内部的实例变量
    访问实例变量的语法:
    读取数据:引用.变量名
    修改数据:引用.变量名=值
    局部变量在栈内存中存储
    成员变量中的实例变量在java对象内部存储,而new的对象在堆内存中存储,即成员变量中的实例变量存储在堆内存当中
    变量分类:
    局部变量:在方法体中声明
    成员变量:在方法体外声明
    成员变量又分为:
    实例变量(类体中定义的变量,比如下面Student类中的num学号变量):前边修饰符没有static
    静态变量:前边修饰符有static
    静态变量存储在方法区内存当中
    三块存储中变化最频繁的是栈内存,最先有数据的是方法区内存,垃圾回收器主要针对的是堆内存
    垃圾回收器:(自动垃圾回收机制 GC机制)
    在堆内存中Java对象成为垃圾数据的时候,即没有更多引用指向他的时候,垃圾回收器会考虑将该Java对象回收
     */

                                                               内存分配图

封装性:

//用户测试类
/*
面向对象有三大特征:封装,继承,多态
封装性:
封装的好处:
1.封装之后看不到事物复杂的那一面,只能看到事物简单的那一面
2.封装之后才会看到真正的"对象“,才会看到真正的"独立体"
3.封装就意味着以后的程序可以重复使用,并且这个事物适应性比较强,在任何场合都可以使用
4.封装之后,对于事物本身,提高了安全性(属性是完全暴露在外部程序中,程序员可以操作对象的细节,导致数据不安全,进行封装,是的不能随意访问对象中的属性)
封装的步骤:
1.所有属性私有化,使用private关键字进行修饰
2.对外提供简单的操作入口,必须通过入口进行访问:两种方式:读取:get,修改:set(方法写在类体中)
set方法的命名规范:
public 返回值类型 set+属性名首字母大写(形参){

}
get方法的命名规范:其中返回值类型的规则和普通方法一样
public 返回值类型 get+属性名首字母大写(形参){

}
get和set方法没有static关键字
有static关键字修饰的方法调用:类名.方法名(实参);
没有static关键字修饰的方法调用:引用.方法名(形参);
 */                         
    /*

构造方法:

    1.构造方法又被称为构造函数/构造器
    2.语法结构:
    [修饰符列表] 构造方法名(形式参数列表){
            构造方法体;
    }
    普通方法的语法结构:
    [修饰符列表] 返回值类型 方法名(形式参数列表){
            方法体;
    }
    对于构造方法来说返回值类型不能指定,不能写void,如果写了就会变成普通方法
    构造方法的方法名必须和类名保持一致
    作用:通过构造方法的调用可以创造对象
    调用:
    普通方法:有static关键字修饰的方法调用:类名.方法名(实参);没有static关键字修饰的方法调用:引用.方法名(形参);
    构造方法:new 构造方法名(实参列表);
    每一个构造方法执行结束后都有返回值,并且返回值类型就是构造方法所在类的类型,由于构造方法的返回值类型就是类本身,所以不需要写
    注释与取消注释:ctrl+/
    多行注释与取消:ctrl+shift+/
    当一个类中没有任何构造方法的时候,系统默认给这个类提供一个无参数的构造方法,方法被称为缺省构造器
    当我们已经在类中定义一个构造方法后,系统将不再默认提供缺省构造器,建议开发中手动提供无参数构造方法
    构造方法支持方法重载机制,若定义一个有参数的方法,定义一个无参数的方法;方法名相同,我们就可以通过调用时控制参数来调用相应的构造方法
    构造方法的另一个作用:创建对象的同时,初始化实例变量的内存空间(给实例变量赋初始默认值)
    成员变量中的实例变量,属于对象级别的变量,必须先有对象才能有实例变量,实例变量的内存空间是在构造方法执行过程中完成初始化的,
    即变量在赋默认值是在构造方法的执行过程中,所以构造方法能够初始化实例变量的内存空间
     */
/*
方法调用的时候,涉及参数传递的问题,传递的时候,java只遵循一种语法机制,
就是将变量中保存的值传过去,只不过有时候传的是字面值,有时候传的是另一个java对象的内存地址
 */

this关键字

/*
1.this是一个引用,this是一个变量,this变量中保存的内存地址指向了堆内存Java对象自身,this存储在JVM堆内存java对象内部
2.创建100个java对象,每一个对象都有this,也就有100个不同的this
  没有static关键字参与的方法被称为实例方法
  没有static关键字参与的变量被称为实例变量
3.this可以出现在实例方法(不带static的方法)中指向当前正在执行动作的对象,this代表当前对象
4.this在多数情况下都是可以省略不写的
5.this不能使用在带有static的方法中
 */
//this不能省略的情况:用来区分局部变量和实例变量时不能省略
/*
this作用:
1.可以使用在实例方法中表示当前对象(this.)
2.可以使用在构造方法当中,通过当前构造方法调用其他构造方法(this(实参))
this.year=1970;
this.month=12;
this.day=23;
//以上的代码和下面有参构造的代码重复,我们可以通过调用下面的构造方法来完成,前提是不能创建新的对象
//new Date(1970,12,23);
//需要采用this来调用,这种方法不会创建新的java对象,这段this调用只能出现在第一行,上面不能写其他代码
//在一个构造方法中只能调用一次其他构造方法,只能写一次this(实参)
  /*
  带有static的方法既可以采用类名.访问,也可以采用创建对象后引用的方式访问,
  但即使采用引用的方式访问,实际执行的时候与引用的对象无关,他会忽视编写的引用.默认为类名.(或者类名.省略)
   */
 */

static关键字

/*
所有的中国人类中的国籍都是中国,这里声明实例变量显然是不合适的,太浪费内存空间,没必要让每一个对象都保留一份"国籍"内存
所有对象国籍一样,这种特征属于类级别的特征,可以提升为整个模版的特征,可以在变量前增加static关键字修饰
加上static修饰的变量被称为静态变量,静态变量在类加载的时候初始化,不需要创建对象,内存就开辟了
静态变量存储在方法区内存当中
所有对象都有这个属性,但是这个属性的值会随着对象的变化而变化,变量声明为实例变量
所有对象都有这个属性,但是所有对象的这个属性的值都一样,变量声明为静态变量,节省内存开销
静态变量在类加载的时候初始化,不需要创建对象,访问的时候直接类名.静态变量名的方式访问
static修饰的所有元素都是类级别的特征,和具体对象无关,也可以使用引用.访问,但与对象无关
 */
/*
1.static关键字可以定义静态代码块
语法格式:
static{
  java语句
}
2.静态代码块在类加载时执行并且只执行一次
3.静态代码块在一个类中可以编写多个,并且遵循自上而下顺序依次执行
4.作用:和具体的需求有关,例如,项目要求在类加载的时候执行代码完成日志的记录,
  这段记录日志的代码就可以编写在静态代码块当中,完成日志记录
//实例代码块/语句块(使用很少)
1.实例代码块可以编写多个,并且遵循自上而下顺序依次执行
2.实例代码块在构造方法执行之前执行,构造方法执行一次,实例代码块就对应执行一次
3.实例代码块执行时机也是一个特殊的时机被称为对象初始化时机
方法定义为静态方法的时机:方法描述的是动作,当所有的对象执行这个动作的时候,
最终产生的影响是一样的,那么这个动作已经不属于一个对象的动作,可以将这个动作提升为类级别的动作,模板级别的动作
当这个动作不需要对象的参与,就可以定义为静态方法
静态方法中无法访问实例变量和实例方法,需要创建对象,后通过引用.访问
 */
/*

继承

关于继承,继承是三大特征之一:封装,继承,多态
基本作用:代码复用,但最重要的作用是:有了继承才有以后方法覆盖和多态机制
继承的语法格式:
[修饰符列表] class 类名 extends 父类名{
       类体=属性+方法
JAVA语言中的继承只支持单继承,一个类只能继承一个类,不能继承多个类
关于继承中的术语:
B类继承A类:
A类称为:父类,基类,超类,superclass
B类称为:子类,派生类,subclass
子类继承父类继承哪些数据:
私有的不支持继承
构造方法不支持继承
其他都可继承
虽然JAVA语言中只支持单继承,但是一个类也可以间接继承其它类
例如:
C extend B{}
B extend A{}
A extend T{}
C直接继承B类,间接继承T,A类
}
JAVA语言中,假设没有继承任何一个类的话,默认继承JAVASE库中的java.lang.Object类
 */

方法的覆盖

/*
回顾方法重载;Overload
在同一个类中,方法名相同,参数列表不同:类型,顺序,个数可以构成方法的重载
关于JAVA语言中方法的覆盖:
方法覆盖又被称为方法重写:Override
此时,我不想三个类都输出动物在移动,比如我猫类输出猫在走猫步,鸟输出鸟儿在飞翔,
此时父类中的方法无法满足子类中的需求,就可以将父类中继承过来的方法进行重写即覆盖
方法覆盖之后,子类在重新调用的时候一定调用方法重写之后的方法
方法覆盖发生在:
1.具有继承关系的子类和父类之间,
2.返回值相同,方法名相同,参数类表相同,
3.访问权限不能更低,可以更高(只能写比public访问权限更高的关键字)
4.抛出异常不能更多,只能更少(以后讲)
私有方法不能继承,所以不能覆盖
构造方法不能继承,所以不能覆盖
静态方法不存在覆盖(讲完多态后解释)
覆盖只针对方法不谈属性
 */

关于Java语言中的多态语法机制

/*
1.Animal,cat,bird类之间的关系:cat继承Animal,bird继承Animal,cat和bird之间没有任何继承关系
2.多态中的概念(前提两种类型必须有继承关系):
向上转型:(up casting)子类向父类转称为向上转型又被称为自动类型转换
向下转型:(down casting)父类向子类转型称为向下转型又被称为强制类型转换(需加强制类型转换符)
 */
    //多态语法机制
    /*
    Animal和cat之间存在继承关系,Animal是父类,cat是子类
    cat is a Animal
    new cat()创建对象的类型是cat,a1这个数据的引用类型是Animal,可见他们进行的类型转换
    子类型转换为父类型,称为向上转换,存在自动类型转换,允许父类型引用指向子类型对象
    以下程序分为编译阶段和运行阶段
    编译阶段编译器检查a1这个引用数据类型为Animal,
    由于Animal.class字节码文件中有move方法所以编译通过了,这个过程称为静态绑定,编译过程绑定
    只有静态绑定成功后才有后续的运行,而在运行阶段,JVM堆内存中创建的对象为cat对象,
    则运行时一定会调用cat对象的move方法此时发生了动态绑定
    和cat中重写不重写没有任何关系,若cat中不重写,它也调用的是cat中从Animal父类中继承过来的方法,无论怎样,都调用cat类中的方法
    父类型引用指向子类型对象导致程序在编译阶段和运行阶段绑定两种不同的形态,这种机制称为多态语法机制
    a2.catchMouse();为什么不能运行,因为在编译阶段,
    编译器检查到a1的类型是Animal类型而在Animal.class字节码文件中没有找到catchMouse方法,
    导致静态绑定失败所以编译失败,更别提运行了
    解决上述问题:
    a1引用的类型是Animal,而Animal类中没有catchMouse方法,我们将a1强制类型转换为cat类型,
    a1的类型是Animal类型(父类),转换为cat类型(子类),需要向下转型(强制类型转换)
    Animal a3=new bird();
    cat a4=(cat) a3;
    以上程序编译没有问题,因为a3是Animal类型,cat类型和Animal类型之间存在继承关系,Animal转cat为向下转型,需强制类型转换,语法合格
    但运行时,会出现异常,因为JVM堆内存当中真实存在的是bird类型,bird对象无法转换为cat对象,所以出现类型转换异常(java.lang.ClassCastException)
    这种异常常常出现在向下转型的时候会发生
    解决:使用instanceof运算符就能解决
    instanceof运算符语法格式:
    引用 instanceof 数据类型
    以上运算符执行结果是布尔类型,结果可能是true/false
    a1 instanceof Animal
    true表示:a1这个引用指向的对象是Animal类型
    false表示:a1这个引用指向的对象不是Animal类型
    */
    /*
    解决类型转换异常的问题
    若a3引用指向的对象是cat类型,则把原来Animal类型强制转换为cat类型,
    若a3指向的对象是bird类型,则把原来的Animal类型强制转换为bird类型,
    可防止在运行的时候出现cat类型的引用指向bird类型的对象,而这两者不存在继承关系,所以不能相互转换,导致运行报错
    在进行强制类型转换前需要加上instanceof运算符进行判断,防止类型转换异常,这是一种编程好习惯
     */
//主人
  //喂养宠物的方法
  /*在这段代码中,`cat`类是一个自定义的类,它描述了猫的属性和行为。当我们声明一个变量或参数为`cat`类型时,
  它实际上是一个引用,即指向`cat`类实例的指针。这个引用指向在内存中实际创建的`cat`对象。因此,当我们将一个`cat`对象的引用作为参数传递给`feed`方法时,
  我们可以通过这个引用来访问和操作这个对象的属性和行为,包括调用`cat`类中定义的成员方法,如`eat`方法。这里相当于主方法中引用tom创建了cat对象,并将tom引用传入feed方法中,从而调用eat方法
  */
/*  public class Master {
  public void feed(cat c){
    c.eat();
  }
  public void feed(dog d){
    d.eat();
  }
}*/
//以上这段代码,并没有使用java语言中的多态机制,Master类的扩展性很差,因为只要插一个新的宠物,Master类中就要加一个新的方法
//目标:提高扩展力,降低程序的耦合度
//主人和dog,cat的dog的关联程度很强,耦合度太高
//多态的作用:降低程序的耦合度,提高程序的扩展力,父类型引用指向子类型对象,
//核心:面向抽象编程,不要面向具体编程
/*
多态在实际开发中的作用,以下面主任喂养宠物的例子来说明
//主人类
主人可以喂养宠物,所以主人可以有喂养这个动作
//宠物类
宠物可以吃东西,所以宠物有吃东西这个动作
 */
  /*
  这里相当于,主方法中a.feed(new dog())或者a,feed(new cat()),将括号中的值
  传到Master类中即pet c=new dog()或者pet c=new cat(),这里含有pet是父类,cat和dog是子类,子类转化为父类是自动类型转换
  这里为父类型引用,可调用子类型中的方法
   */

final关键字

/*
1.final修饰的类无法被继承
2.final修饰的方法无法被覆盖
3.final修饰的变量一旦赋值后,不可重新赋值
4.final修饰的实例变量,系统规定,修饰后实例变量必须手动赋值,不能采用默认值
//实例变量有默认值,final修饰的变量一旦赋值后就不可重新赋值,综合考虑,最终决定final关键字修饰的实例变量必须手动赋值,不可采用默认值
5.final修饰的引用,一旦指向某个对象之后,不能在指向其他对象,被指向的对象无法被垃圾回收器回收,但指向对象内部的内存是可以被修改的
6.final修饰的实例变量一般是不可变的,这种变量一般和static联合使用,被称为"常量"
 */

关于JAVA语言当中的包机制:

/*
1.java中引入package这种语法机制主要为了方便程序管理,
不同功能的类被放到不同的软件包当中查找比较方便,管理比较方便,易维护
2.定义package:在Java源程序的第一行编写package语句
3.package只能编写一个语句
4.语法结构:package 包名;
5.包名的命名规范:公司域名倒序+项目名+模块名+功能名
6.包名要求全部小写,包名也是标识符,一个包将来对应一个目录
例如:package com.bjpowernode.javase.day1//4个目录(目录间用点隔开)
7.使用package机制后,类名不再是package1了,类名变成com.bjpowernode.javase.day1.package1
8.如何运行:先编译,编译后将源程序文件和生成的class文件放到包名指定的目录下,才能运行,在该类下创建对象不能直接写类名,
要将包名一起写上,当两个测试java文件在一个包中时包名可以省略
9.简化上述写法:import 包名.* 即导入包名
10.import用来导入类,同一个包下的类不需要导入,不在同一个包下的类需要手动导入,需要编写在package语句下,class语句上
导入类:import 类名
导入包:import 包名.*
11.不是java.lang包下,并且不在同一个包下的时候,需要import进行引入
 */

访问控制权限

/*
访问控制权限修饰符:
1.来控制元素的访问范围
2.访问控制权限修饰符包括:
public     表示公开的,任何位置都能访问
private    表示私有的,只能在本类中访问
protected  同包下,子类
缺省        同包下
3.访问控制权限修饰符可以修饰类,变量,方法
4.当某个数据只希望子类使用时,用protected进行修饰
5.使用范围:private<缺省<protected<public
 */

super关键字

/*
this和super对比学习
this:
this出现在实例方法和构造方法中
this的语法:this.和this()
this不能出现在静态方法中
super:
super能出现在实例方法和构造方法中
super的语法是:super.和super()
super不能使用在静态方法中
super.大部分情况下是可以省略的,父类中有的属性,子类中也有同名属性,如果想在子类中访问父类的属性特征,如果省略,则访问的都是当前对象的内容(子类中)
父类中和子类中存在相同的属性或方法,如果想在子类中访问父类的数据(属性或方法),必须加上super.来区分
super只能出现在构造方法的第一行,通过当前的构造方法去调用父类中的构造方法,目的是:创建子类对象的时候,先初始化父类型特征
super()表示通过子类构造方法调用父类的构造方法
当一个构造方法第一行既没有this()又没有super()时默认会有一个super()表示当前子类的构造方法调用父类的无参数构造方法,所以必须保证父类的无参数构造方法是存在的
总结:
super.属性名 访问父类属性
super.方法名(实参)访问父类方法
super(实参)调用父类的构造方法
 */
//super(实际参数列表)
//解决父类的私有变量在子类中访问的问题
//super什么时候不能省略
//JAVA语言中区分子类和父类中的同名属性
/*
this.name 当前对象的name属性
super.name 当前对象的父类型特征中的name属性
 */
//this可以单独用,super不能单独用,必须用super.才行
//super不是引用,super也不保存内存地址,super也不指向任何对象
//super只是代表当前对象内部的那一块父类型特征
//super.不仅可以访问属性,也可以访问方法

抽象类

/*
抽象类:是类和类之间有共同特征,将这些具有共同特征的类进一步抽象形成抽象类,由于类本身是不存在的,所以抽象类无法创建对象(无法实例化)
抽象类和抽象类实际上还有可能有共同特征,还可以进一步抽象
类到对象是实例化,对象到类是抽象
抽象类:类和类之间有共同特征,将这些特征提取出来,形成的就是抽象类,属于引用数据类型
语法:
[修饰符列表] abstract class 类名{
      类体;
}
抽象类:                            银行账户类
类:          信用卡类                                          储蓄卡类         (类是现实世界不存在的,人类大脑思考总结的结果)
对象:小明的信用卡   小花的信用卡                         小明的储蓄卡     小美的储蓄卡        (对象是现实世界存在的)
1.抽象类无法实例化,无法创建对象,有构造方法,供子类使用
2.抽象类是用来被子类所继承的
3.final和abstract是对立的,二者不能同时出现
4.抽象类的子类还可以是抽象类
5.抽象方法:没有实现的方法,没有方法体的方法
例:public abstract void doSome();
特点:没有方法体,以分号结尾,前面修饰符列表中有abstract关键字
6.抽象类中可以有抽象方法,也可以有非抽象方法,但抽象方法必须出现在抽象类中
 */
//一个非抽象类继承抽象类,必须将抽象类中的方法进行覆盖(重写)
//若子类也和父类一样定义成抽象类的话,那么继承过来的抽象方法也可以不覆盖(重写)


从键盘输入

//导入该包
import java.util.Scanner;
public class import键盘输入 {
  public static void main(String[] args) {
    Scanner c=new Scanner(System.in);
    System.out.println("请输入:");
    String name=c.next();
    System.out.println("您输出的名字是:"+name);
  }
}

接口

/*
1.接口是引用数据类型,编译后也是class字节码文件
2.接口是完全抽象的(抽象类是半抽象的),接口是特殊的抽象类
3.接口的定义语法:不能有class关键字
[修饰符列表] interface 接口名{
}
类:
[修饰符列表] class 类名{
}
4.接口支持多继承,一个接口可以继承多个接口
5.接口中只包含常量和抽象方法
6.接口中所有的元素都是public修饰,都是公开的
7.接口中的抽象方法定义时,public static可以省略
8.接口中只能定义抽象方法,而抽象方法不能带有方法体,所以接口中的方法不能有方法体
9.接口中的常量,public static final可以省略
10.类和类之间叫继承,类和接口之间叫实现,但仍可用继承去看待
11.继承使用extends关键字,实现使用implements关键字
12.接口中不能创建对象,要创建对象也是实现的子类中创建对象,也不能实例化:new MyMath();
 */
//接口和接口之间支持多继承,一个类可以实现多个接口,弥补了Java中类和类只支持单继承,而现实世界中存在多继承,Java接口弥补了多继承
//向下转型前养成好习惯,加上instanceof进行判断
//继承和实现都存在
//extends关键字在前
//implements关键字在后
//接口通常提取的是行为动作
//接口在开发中的作用
/*
类似于多态在开发中的作用
多态的作用:面向抽象编程,不是面向具体编程,降低程序的耦合度,提高程序的扩展力
接口的作用:面向抽象编程以后可以改为面向接口编程,有了接口就会可插拔,扩展力就强
 */
/*
饭馆吃饭,有菜单,有厨师,有顾客
 */
//以后进行大项目的开发,一般都是将大项目分成一个模块,一个模块,模块和模块之间采用接口连接,降低耦合度
/*
is a,has a,like a关系
is a:
cat is a animal
凡是能够满足is a的表示继承关系
A extends B
has a:
i has a pen
凡是能够满足has a的表示关联关系,通常以属性的形式存在
A{
   B b;
}
like a;像
cooker like a foodMenu(厨师就像一个菜单一样)
凡是能够满足like a表示实现关系,通常是类实现接口
A implements B
 */

完整代码:

https://github.com/DeveloperWhite/Java

评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值