接口

接口

一、接口概述

接口在生活中随处可见。例如:屋子里的五孔墙插。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YSyus1JD-1615184665396)(12_接口/西门子五孔墙插.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k71GSZZj-1615184665407)(12_接口/欧普五孔墙插.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nr6wZCJU-1615184665414)(12_接口/公牛五孔墙插.png)]

为什么不同厂商生产的面板装在你家里之后你都可以使用呢?因为他们是遵守同样的规范生产的。

其实接口就是一组规范或标准,只要符合规范,大家都可以使用。

除了生活中的接口,与计算机相关的接口也随处可见。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-giISJqo7-1615184665431)(12_接口/USB接口.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ndxXcTqt-1615184665434)(12_接口/USB鼠标.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qPcalNd2-1615184665436)(12_接口/USB键盘.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vCIQmRKv-1615184665438)(12_接口/U盘.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q8Aub0to-1615184665441)(12_接口/USB移动硬盘.png)]

虽然我们往电脑上插的硬件各不相同,但是他们都能正常的工作,之所以能正常工作是因为他们都是遵守USB规范生产的。

再例如:某公司招聘Java开发工程师,要求能写代码,能写需求文档,能与客户沟通项目。这就是一个接口,它只规定要做什么事情,谁能胜任这些事,谁就可以入职。

接口就是一种公共的规范标准,只要遵守规范,谁都可以使用。Java中的接口更多是对行为的抽象,它只规定有什么方法,自身不提供实现,由遵守规范的类来提供实现。

接口的实现类:实现接口的类称为接口的实现类。

二、接口的定义

在Java中,使用interface关键字来定义接口。

接口定义的语法:

public interface 接口名{
    //静态常量
    //抽象方法、默认方法、静态方法
}

接口示例:

public interface Driving {
	//开车
	public abstract void drive();
}

三、接口的实现类

接口的作用是定义标准和规范,实现类负责实现接口中的方法。

(1)类实现接口的语法格式

类通过implements关键字实现接口。

语法格式:

public class 类名 implements 接口名{
    //属性
    //方法
}

public class 类名 extends 父类名 implements 接口名{
    //属性
    //方法
}

(2)接口的实现类示例

  1. 需求:设计教师、程序员类,教师能教课,程序员可以写代码,他们都会开车。—千万不要定义一个司机(Driver)类,让教师和程序员继承于Driver,他们不满足is a的关系,不能滥用继承。

  2. 代码:

    父类Person

    public class Person {
    	private String name;	//姓名
    	private int age;		//年龄
    	
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	
    	public Person() {
    		super();
    	}
    	public Person(String name, int age) {
    		super();
    		this.name = name;
    		this.age = age;
    	}
    	
    	public void showInfo() {
    		System.out.println("姓名:" + name + ", 年龄:" + age);
    	}
    }
    

    教师Teacher

    public class Teacher extends Person {
        public Teacher() {
    		super();
    	}
    
    	public Teacher(String name, int age) {
    		super(name, age);
    	}
    	//教课
    	public void teach() {
    		System.out.println(this.getName() + "正在授课");
    	}
    }
    

    程序员Programmer

    public class Programmer extends Person {
        public Programmer() {
    		super();
    	}
    
    	public Programmer(String name, int age) {
    		super(name, age);
    	}
    
    	//写代码
    	public void writeProject() {
    		System.out.println(this.getName() + "正在写项目");
    	}
    }
    

    驾驶接口Driving

    public interface Driving {
    	//开车
    	public abstract void drive();
    }
    

    教师实现Driving接口

    public class Teacher extends Person implements Driving {
    	
    	public Teacher() {
    		super();
    	}
    
    	public Teacher(String name, int age) {
    		super(name, age);
    	}
    
    	//教课
    	public void teach() {
    		System.out.println(this.getName() + "正在授课");
    	}
    
    	@Override
    	public void drive() {
    		System.out.println("教师开车");
    	}
    	
    }
    

    程序员实现Driving接口

    public class Programmer extends Person implements Driving{
    	
    	public Programmer() {
    		super();
    	}
    
    	public Programmer(String name, int age) {
    		super(name, age);
    	}
    
    	//写程序
    	public void writeProject() {
    		System.out.println(this.getName() + "正在写项目");
    	}
    
    	@Override
    	public void drive() {
    		System.out.println("程序员开车去兜风");
    	}
    }
    

    测试代码:

    public class ClassTest {
    
    	public static void main(String[] args) {
    		Teacher t = new Teacher("张三", 32);
    		t.showInfo();//继承过来的方法
    		t.teach();//自己的方法
    		t.drive();//实现的接口中的方法
            Driving d = new Teacher("李四", 25);//多态
            d.drive();
    		
    		Programmer p = new Programmer("王五", 24);
    		p.showInfo();//继承过来的方法
    		p.writeProject();//自己的方法
    		p.drive();//实现的接口中的方法
    	}
    
    }
    

    在设计类的时候,一旦一个类实现了接口中的方法,我们就认为这个类get了新的功能。例如:Teacher遵守了Driving接口,实现了接口中的方法,就可以认为教师具有开车的功能。Programmer遵守了Driving接口,实现了接口中的方法,就可以认为程序员具有开车的功能。

    接口可以当成一种数据类型来看待。Teacher和Programmer都实现了Driving接口,都会开车,他们可以看成Driving类型的对象,即接口可以看作父类

    接口弥补了Java只能单继承的缺陷,变相实现了多继承。

    在Java中多态一共2种:

    1. 父类引用指向子类对象的多态。------继承中的多态(继承关系)
    2. 接口引用指向实现类对象的多态。------接口中的多态(实现关系)

四、接口的成员特点

接口可以包含自己的成员,包括属性和方法。

(1)接口中的属性

有如下接口,MyInterface

public interface MyInterface {
	int a = 10;
	public int b = 20;
	public static int c = 30;
	public static final int d = 40;
}

有如下实现类,MyInterfaceImpl

public class MyInterfaceImpl implements MyInterface {

}

测试代码:

public class ClassTest {

	public static void main(String[] args) {
		
		MyInterface my = new MyInterfaceImpl();
		System.out.println(my.a);
		System.out.println(MyInterface.a);//说明a被static修饰了
		//my.a = 100;//final修饰的变量不能改值
		System.out.println(my.b);
		System.out.println(MyInterface.b);//说明b被static修饰了
		//my.b = 200;//final修饰的变量不能改值
		System.out.println(my.c);
		System.out.println(MyInterface.c);
		//my.c= 300;//接口中的属性默认是  public  static  final修饰
		System.out.println(my.d);
		System.out.println(MyInterface.d);//因为d是static修饰的,所以可以用类名访问。
		//my.d= 400;//final修饰的变量不能改值
	}

}

通过测试,我们发现a隐含了修饰符public、final和static,b隐含了修饰符static、final,c隐含了修饰符final。

总结:接口中只能包含public static final修饰的属性,即只能包含静态常量。–注意常量一般使用纯大写字母命名。

(2)反编译工具查看接口中的属性

程序的运行流程:首先,源代码经过编译得到字节码文件;然后,运行字节码得到执行结果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lRjuKTjh-1615184665443)(12_接口/Java代码执行流程.png)]

反编译:把字节码文件还原成Java源文件。

**反编译需要借助反编译工具。**目前有很多反编译工具,例如:JD-GUI、JadX、CFR、luyten等

我们使用JD-GUI反编译MyInterface。JD-GUI工具如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YePim4xr-1615184665448)(12_接口/jd-gui.png)]

反编译后的代码:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5eIKqKgD-1615184665451)(12_接口/接口反编译1.png)]

由此可见,接口中定义的属性,默认就是public static final修饰的。即接口中的属性只能是静态常量!

(3)接口中的方法

接口中不能有构造方法、初始化代码块、静态代码块!

接口不是类,它只声明接口中有什么方法,但自身不实现。只定义不实现的方法就是我们前面学的抽象方法。

public interface MyInterface {
	int a = 10;
	public int b = 20;
	public static int c = 30;
	public static final int d = 40;
	
//	public MyInterface() {
//		
//	}
	
//	{
//		
//	}
	
//	static {
//		
//	}
	
	//接口只定义包含什么方法,但是自身不实现。
	public abstract void method1();
	public void method2();
	void method3() ;

}

实现类MyInterfaceImpl:

public class MyInterfaceImpl implements MyInterface {

	@Override
	public void method1() {
		System.out.println("method1");
	}

	@Override
	public void method2() {
		System.out.println("method2");
	}

	@Override
	public void method3() {
		System.out.println("method3");
	}

}

测试代码:

public class ClassTest {

	public static void main(String[] args) {
		
		MyInterface my = new MyInterfaceImpl();
		System.out.println(my.a);
		System.out.println(MyInterface.a);//说明a被static修饰了
		//my.a = 100;//final修饰的变量不能改值
		System.out.println(my.b);
		System.out.println(MyInterface.b);//说明b被static修饰了
		//my.b = 200;//final修饰的变量不能改值
		System.out.println(my.c);
		System.out.println(MyInterface.c);
		//my.c= 300;//接口中的属性默认是  public  static  final修饰
		System.out.println(my.d);
		System.out.println(MyInterface.d);//因为d是static修饰的,所以可以用类名访问。
		//my.d= 400;//final修饰的变量不能改值
		
		my.method1();
		my.method2();
		my.method3();
	}

}

通过测试,我们发现method2隐含abstract,method3隐含了public abstract。

总结:接口中的方法默认修饰符是public abstract,即方法是抽象方法。

(4)接口中定义静态方法和默认方法

从Java8开始,接口中可以定义静态方法和默认方法。静态方法和默认方法不再是方法的声明,而是有方法体。

public interface MyInterface {
	int a = 10;
	public int b = 20;
	public static int c = 30;
	public static final int d = 40;
	
//	public MyInterface() {
//		
//	}
	
//	{
//		
//	}
	
//	static {
//		
//	}
	
	//接口只定义包含什么方法,但是自身不实现。
	public abstract void method1();
	public void method2();
	void method3() ;
	
	//从Java8开始,接口中除了抽象方法以外,还可以包含2种方法
	
	//1. 静态方法。
	public static void staticMethod() {
		System.out.println("我是接口中的静态方法");
	}
	
	//2. 默认方法
	public default void defaultMethod() {
		System.out.println("我是接口中的默认方法,默认方法必须要加default关键字");
	}

}

MyInterfaceImple类:

public class MyInterfaceImpl implements MyInterface {

	@Override
	public void method1() {
		System.out.println("method1");
	}

	@Override
	public void method2() {
		System.out.println("method2");
	}

	@Override
	public void method3() {
		System.out.println("method3");
	}
	
	public static void staticMethod() {
		System.out.println("子类的静态方法");
	}
	
	//重写接口中的默认方法
	@Override
	public void defaultMethod() {
		System.out.println("重写了接口中的默认方法");
	}

}

测试代码:

public class ClassTest {

	public static void main(String[] args) {
		
		MyInterface my = new MyInterfaceImpl();
		System.out.println(my.a);
		System.out.println(MyInterface.a);//说明a被static修饰了
		//my.a = 100;//final修饰的变量不能改值
		System.out.println(my.b);
		System.out.println(MyInterface.b);//说明b被static修饰了
		//my.b = 200;//final修饰的变量不能改值
		System.out.println(my.c);
		System.out.println(MyInterface.c);
		//my.c= 300;//接口中的属性默认是  public  static  final修饰
		System.out.println(my.d);
		System.out.println(MyInterface.d);//因为d是static修饰的,所以可以用类名访问。
		//my.d= 400;//final修饰的变量不能改值
		
		my.method1();
		my.method2();
		my.method3();
		
		MyInterface.staticMethod();
		MyInterfaceImpl.staticMethod();
		//my.staticMethod();//接口中的静态方法,只能用接口名调用,不能用对象调用。(类中的静态方法既可以用类名调用,也可以用对象调用,推荐使用类名调用)
		my.defaultMethod();//默认方法是对象方法,用对象来调用。
	}

}

接口中的静态方法和类中的静态方法不同。接口中的静态方法只能用接口名调用,不能用对象调用。类中的静态方法,既可以用类名调用,也可以用对象调用。

接口中的默认方法,必须用default关键字修饰。被default关键字修饰的方法不再是抽象方法,可以给出默认实现。之所以这么设定,是避免了接口中增加新方法影响已有实现类的使用。(如果没有默认实现,所有已有的实现类,都必须实现新增的方法。)

(5)接口的成员总结

**接口中可以包含属性:必须是public static final修饰的属性,即静态常量!**变量名命名的时候大写。

接口中可以包含方法

  1. public abstract修饰的抽象方法。
  2. 静态方法(public static修饰的方法)
  3. 默认方法(public default修饰的方法)

接口中不能包含构造方法、初始化代码块、静态代码块。

五、类实现多个接口

一个类可以实现多个接口,接口与接口之间用逗号隔开。

语法格式

public class 类名 implements 接口名1,接口名2,接口名3{
    //类的成员
}

或者

public class 类名 extends 父类名 implements 接口名1,接口名2,接口名3{
    //类的成员
}
  1. 需求:设计教师、程序员类,教师能教课,程序员可以写代码,他们都会开车,都会做饭。提示:开车定义在Driving接口中,做饭定义在Cooking接口中,让教师和程序员实现2个接口。

  2. 代码:

    父类Person:

    public class Person {
    	private String name;	//姓名
    	private int age;		//年龄
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	public Person() {
    		super();
    	}
    	public Person(String name, int age) {
    		super();
    		this.name = name;
    		this.age = age;
    	}
    	
    	//toString方法
    	public String toString() {
    		return "姓名:" + name + ",年龄:" + age;
    	}
    	
    }
    

    接口Driving:

    public interface Driving {
    	//开车
    	public abstract void drive();
    }	
    

    接口Cooking:

    public interface Cooking {
    	//做饭
    	public abstract void cook();
    }
    

    教师Teacher类:

    public class Teacher extends Person implements Driving, Cooking{
    
    	public Teacher() {
    		super();
    	}
    
    	public Teacher(String name, int age) {
    		super(name, age);
    	}
    	
    	//教课
    	public void teach() {
    		System.out.println(this.getName() + "正在授课");
    	}
    	
    	//Driving接口中的方法
    	@Override
    	public void drive() {
    		System.out.println("教师开车");
    	}
    
    	//Cooking接口中的方法
    	@Override
    	public void cook() {
    		System.out.println("教师做饭");
    	}
    }
    

    程序员Programmer类:

    public class Programmer extends Person implements Driving, Cooking {
    
    	public Programmer() {
    		super();
    	}
    
    	public Programmer(String name, int age) {
    		super(name, age);
    	}
    
    	//写程序
    	public void writeProject() {
    		System.out.println(this.getName() + "正在写项目");
    	}
    
    	//Cooking接口中的方法
    	@Override
    	public void cook() {
    		System.out.println("程序员做饭");
    	}
    
        //Driving接口中的方法
    	@Override
    	public void drive() {
    		System.out.println("程序员开车");
    	}
    
    }
    

    测试代码:

    public class ClassTest {
    
    	public static void main(String[] args) {
    		Teacher t = new Teacher("马云", 56);
    		//System.out.println(t.toString());
    		System.out.println(t);//当你打印对象的时候,默认调用对象的toString
    		t.teach();
    		t.drive();
    		t.cook();
    		
    		Cooking c = new Teacher("马云", 56);
    		System.out.println(c);
    		c.cook();
    		
    		Driving d = new Teacher("马云", 56);
    		System.out.println(d);
    		d.drive();
    		System.out.println("------");
    		Programmer p = new Programmer("马化腾", 52);
    		System.out.println(p);
    		p.writeProject();
    		p.cook();
    		p.drive();
    		
    		Cooking c2 = new Programmer("马化腾", 52);
    		c2.cook();
    		
    		Driving d2 = new Programmer("马化腾", 52);
    		d2.drive();
    		
    	}
    
    }
    

六、接口继承另外的接口

接口可以继承另外的接口,使用extends关键字继承别的接口,如果要继承多个接口,父接口之间用逗号隔开。

public interface 接口名 extends 接口1,接口2,接口3{
    //方法
}

示例:

MyInterface接口:

public interface MyInterface {
	public abstract void myInterfaceMethod();
}

MyInterface1接口:

public interface MyInterface1 {
	public abstract void myInterface1Method();
}

MyInterface2接口:

public interface MyInterface2 extends MyInterface, MyInterface1{
	public abstract void myInterface2Method();
}

实现类InterfaceImpl:

//要实现MyInterface2以及所有父接口中声明的方法
public class InterfaceImpl implements MyInterface2 {

	@Override
	public void myInterfaceMethod() {
		System.out.println("MyInterface中的方法");
	}

	@Override
	public void myInterface1Method() {
		System.out.println("MyInterface1中的方法");
	}

	@Override
	public void myInterface2Method() {
		System.out.println("MyInterface2中的方法");
	}

}

测试代码:

public class ClassTest {

	public static void main(String[] args) {
		InterfaceImpl impl = new InterfaceImpl();
		impl.myInterfaceMethod();//MyInterface中的方法
		impl.myInterface1Method();//MyInterface1中的方法
		impl.myInterface2Method();//MyInterface2中的方法
        
        MyInterface2 my = new InterfaceImpl();
		my.myInterfaceMethod();//MyInterface中的方法
		my.myInterface1Method();//MyInterface1中的方法
		my.myInterface2Method();//MyInterface2中的方法
	}

}

实现类不但要实现接口中声明的方法,还要实现接口的父接口中声明的方法。

七、接口和抽象类的区别

抽象类:用abstract修饰的类称为抽象类。

接口:是一组规范和标准,往往是对行为的抽象。

(1)相同点

  1. 接口和抽象类都不能实例化对象。
  2. 接口和抽象类都可以使用多态。
  3. 接口和抽象类都可以包含抽象方法。
  4. 一个类如果实现接口必须实现全部的抽象方法(或者自身定义为抽象类,不现实接口中的方法,由子类去实现),一个类继承于抽象类,必须实现全部的抽象方法(或者自身定义为抽象类,不现实接口中的方法,由子类去实现)。

(2)不同点

  1. 接口中的属性只能包含静态常量(public static final)。抽象类中的属性可以包含:实例变量、静态变量、常量(静态、非静态),而且访问修饰符可以是(public、缺省、protected、private)
  2. 接口中的方法通常是抽象方法(Java8开始,可以有默认方法和静态方法)。抽象类中的方法可以包含:实例方法(含getter、setter)、静态方法、抽象方法。
  3. 接口不能有构造方法(它不是类),抽象类可以包含构造方法。
  4. 接口中不能包含初始化块、静态代码块。抽象类中可以包含初始化块和静态代码块。
  5. 接口中的默认方法必须用default修饰。抽象类中不需要default就可以实现方法。
  6. 接口可以继承别的接口,而且可以继承多个。抽象类可以继承别的类,但只能继承一个类。
  7. 一个普通类,只能有一个父类(包括抽象类),但可以实现多个接口。

八、接口示例

  1. 需求:定义一个英雄类Hero,包含姓名(name)、血量(hp)、护甲(armor)。定义一个物理攻击英雄类ADHero,定义一个物理攻击的接口AD,定义一个魔法攻击英雄类APHero,定义一个魔法攻击的接口AP,定义一个既能物理攻击也能魔法攻击的英雄ADAPHero,并编写代码测试效果。

  2. 代码:

    父类Hero:

    public class Hero {
    	private String name;	//英雄的名字
    	private int hp;			//英雄的血量
    	private int armor;		//英雄的护甲
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getHp() {
    		return hp;
    	}
    	public void setHp(int hp) {
    		this.hp = hp;
    	}
    	public int getArmor() {
    		return armor;
    	}
    	public void setArmor(int armor) {
    		this.armor = armor;
    	}
    	public Hero() {
    		super();
    	}
    	public Hero(String name, int hp, int armor) {
    		super();
    		this.name = name;
    		this.hp = hp;
    		this.armor = armor;
    	}
    	
    	@Override
    	public String toString() {
    		return "Hero [name=" + name + ", hp=" + hp + ", armor=" + armor + "]";
    	}
    	
    }
    

    接口AD:

    public interface AD {
    	//物理攻击
    	public abstract void physicAttack(Hero hero);
    }
    

    接口AP:

    public interface AP {
    	//魔法攻击
    	public abstract void magicAttack(Hero hero);
    }
    

    ADHero类:

    public class ADHero extends Hero implements AD {
    
    	
    	public ADHero() {
    		super();
    	}
    
    	public ADHero(String name, int hp, int armor) {
    		super(name, hp, armor);
    	}
    
    	@Override
    	public void physicAttack(Hero hero) {
    		System.out.println(this.getName() + "正在物理攻击" + hero.getName());
    	}
    
    }
    

    APHero类:

    public class APHero extends Hero implements AP {
    
    	@Override
    	public void magicAttack(Hero hero) {
    		System.out.println(this.getName() + "魔法攻击" + hero.getName());
    	}
    
    	public APHero() {
    		super();
    	}
    
    	public APHero(String name, int hp, int armor) {
    		super(name, hp, armor);
    	}
    
    }
    

    ADAPHero类:

    public class ADAPHero extends Hero implements AD, AP {
    
    	public ADAPHero() {
    		super();
    	}
    
    	public ADAPHero(String name, int hp, int armor) {
    		super(name, hp, armor);
    	}
    
    	@Override
    	public void magicAttack(Hero hero) {
    		System.out.println(this.getName() + "魔法攻击" + hero.getName());
    	}
    
    	@Override
    	public void physicAttack(Hero hero) {
    		System.out.println(this.getName() + "正在物理攻击" + hero.getName());
    	}
    
    }
    

    测试代码:

    public class ClassTest {
    
    	public static void main(String[] args) {
    		ADHero hero1 = new ADHero("剑姬", 1000, 300);
    		System.out.println(hero1);//System.out.println(hero1.toString());
    		APHero hero2 = new APHero("安妮", 700, 280);
    		System.out.println(hero2);
    		ADAPHero hero3 = new ADAPHero("卡莎", 800, 300);
    		System.out.println(hero3);
    		
    		hero1.physicAttack(hero2);
    		hero2.magicAttack(hero1);
    		
    		hero3.physicAttack(hero1);
    		hero3.magicAttack(hero1);
    
    	}
    
    }
    

九、总结

接口是一组规范和标准,往往是对行为的抽象。

使用interface关键字定义接口。

接口中可以包含:静态常量、抽象方法、默认方法、静态方法。

接口不能实例化对象。

接口和实现类主要服务于多态,接口作为数据类型,指向实现类创建的对象。

类通过implements实现接口(需实现全部的抽象方法)。如果不实现接口中定义的方法,可以定义成抽象类,由子类实现。

一个类可以实现多个接口。接口可以继承接口,父接口可以是多个。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值